[Ibis] Rename to 'Kanagawa' (#7832)

This commit is contained in:
John Demme 2024-11-25 14:23:31 -05:00 committed by GitHub
parent 83b5ff3910
commit 58665c5921
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
97 changed files with 2702 additions and 2673 deletions

View File

@ -50,8 +50,8 @@ lib/Target/ExportSMTLIB @maerhart
# SV
**/Dialect/SV @darthscsi
# Ibis
**/Dialect/Ibis @teqdruid @mortbopet @blakep-msft
# Kanagawa
**/Dialect/Kanagawa @teqdruid @mortbopet @blakep-msft
## Infra

View File

@ -1,3 +0,0 @@
# 'ibis' Dialect
[include "Dialects/Ibis.md"]

View File

@ -1,13 +1,13 @@
# `ibis` Dialect Rationale
# `kanagawa` Dialect Rationale
## Lowering flow
1. Containerization:
At this level, one may have relative references to ports `get_port` accesses
to `!ibis.scoperef`s
to `!kanagawa.scoperef`s
2. Tunneling:
Relative `!ibis.scoperef` references are defined via `ibis.path` operations.
In this pass, we lower `ibis.path` operations by tunneling `portref`s through
Relative `!kanagawa.scoperef` references are defined via `kanagawa.path` operations.
In this pass, we lower `kanagawa.path` operations by tunneling `portref`s through
the instance hierarchy, based on the `get_port` operations that were present
in the various containers. After this, various `portref<in portref<#dir, T>>`
ports are present in the design, which represents the actual ports that are
@ -27,9 +27,9 @@
In cases where children drive parent ports, the prior case may create
situations where a container drives its own input ports (and by extension, no
other instantiating container is expected to drive that port of the instance,
if the IR is correct). We thus run `ibis-clean-selfdrivers` to replace these
if the IR is correct). We thus run `kanagawa-clean-selfdrivers` to replace these
self-driven ports by the actual values that are being driven into them.
5. HW lowering:
At this point, there no longer exist any relative references in the Ibis IR,
At this point, there no longer exist any relative references in the Kanagawa IR,
and all instantiations should (if the IR is correct) have all of their inputs
driven. This means that we can now lower the IR to `hw.module`s.

View File

@ -0,0 +1,3 @@
# 'kanagawa' Dialect
[include "Dialects/Kanagawa.md"]

View File

@ -44,9 +44,9 @@ This document describes the available CIRCT passes and their contracts.
[include "HWPasses.md"]
## Ibis Dialect Passes
## Kanagawa Dialect Passes
[include "IbisPasses.md"]
[include "KanagawaPasses.md"]
## LLHD Dialect Passes

View File

@ -27,11 +27,11 @@ add_subdirectory(Moore)
add_subdirectory(MSFT)
add_subdirectory(OM)
add_subdirectory(Pipeline)
add_subdirectory(Kanagawa)
add_subdirectory(RTG)
if (CIRCT_INCLUDE_TESTS)
add_subdirectory(RTGTest)
endif()
add_subdirectory(Ibis)
add_subdirectory(Seq)
add_subdirectory(Sim)
add_subdirectory(SMT)

View File

@ -1,21 +0,0 @@
add_circt_dialect(Ibis ibis)
add_circt_dialect_doc(Ibis ibis)
set(LLVM_TARGET_DEFINITIONS IbisPasses.td)
mlir_tablegen(IbisPasses.h.inc -gen-pass-decls)
add_public_tablegen_target(CIRCTIbisTransformsIncGen)
add_circt_doc(IbisPasses IbisPasses -gen-pass-doc)
set(LLVM_TARGET_DEFINITIONS IbisInterfaces.td)
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)
mlir_tablegen(IbisAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=ibis)
mlir_tablegen(IbisAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=ibis)
add_public_tablegen_target(MLIRIbisEnumsIncGen)
add_dependencies(circt-headers MLIRIbisEnumsIncGen)

View File

@ -1,29 +0,0 @@
//===- IbisPassPipelines.h - Ibis pass pipelines -----------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_IBIS_IBISPASSPIPELINES_H
#define CIRCT_DIALECT_IBIS_IBISPASSPIPELINES_H
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "mlir/Pass/PassManager.h"
#include <memory>
#include <optional>
namespace circt {
namespace ibis {
// Loads a pass pipeline to transform low-level Ibis constructs.
void loadIbisLowLevelPassPipeline(mlir::PassManager &pm);
// Loads a pass pipeline to transform high-level Ibis constructs.
void loadIbisHighLevelPassPipeline(mlir::PassManager &pm);
} // namespace ibis
} // namespace circt
#endif // CIRCT_DIALECT_IBIS_IBISPASSPIPELINES_H

View File

@ -0,0 +1,21 @@
add_circt_dialect(Kanagawa kanagawa)
add_circt_dialect_doc(Kanagawa kanagawa)
set(LLVM_TARGET_DEFINITIONS KanagawaPasses.td)
mlir_tablegen(KanagawaPasses.h.inc -gen-pass-decls)
add_public_tablegen_target(CIRCTKanagawaTransformsIncGen)
add_circt_doc(KanagawaPasses KanagawaPasses -gen-pass-doc)
set(LLVM_TARGET_DEFINITIONS KanagawaInterfaces.td)
mlir_tablegen(KanagawaInterfaces.h.inc -gen-op-interface-decls)
mlir_tablegen(KanagawaInterfaces.cpp.inc -gen-op-interface-defs)
add_public_tablegen_target(MLIRKanagawaInterfacKanagawancGen)
add_dependencies(circt-headers MLIRKanagawaInterfacKanagawancGen)
set(LLVM_TARGET_DEFINITIONS Kanagawa.td)
mlir_tablegen(KanagawaEnums.h.inc -gen-enum-decls)
mlir_tablegen(KanagawaEnums.cpp.inc -gen-enum-defs)
mlir_tablegen(KanagawaAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=kanagawa)
mlir_tablegen(KanagawaAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=kanagawa)
add_public_tablegen_target(MLIRKanagawaEnumsIncGen)
add_dependencies(circt-headers MLIRKanagawaEnumsIncGen)

View File

@ -1,4 +1,4 @@
//===- Ibis.td - Definition of Ibis dialect -------------------------------===//
//===- Kanagawa.td - Definition of Kanagawa dialect -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,15 +6,15 @@
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_IBIS_TD
#define CIRCT_DIALECT_IBIS_TD
#ifndef CIRCT_DIALECT_KANAGAWA_TD
#define CIRCT_DIALECT_KANAGAWA_TD
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/OpBase.td"
include "mlir/Interfaces/FunctionInterfaces.td"
include "circt/Dialect/Ibis/IbisDialect.td"
include "circt/Dialect/Ibis/IbisTypes.td"
include "circt/Dialect/Ibis/IbisOps.td"
include "circt/Dialect/Kanagawa/KanagawaDialect.td"
include "circt/Dialect/Kanagawa/KanagawaTypes.td"
include "circt/Dialect/Kanagawa/KanagawaOps.td"
#endif // CIRCT_DIALECT_IBIS_TD
#endif // CIRCT_DIALECT_KANAGAWA_TD

View File

@ -1,4 +1,4 @@
//===- IbisDialect.h - Definition of Ibis dialect ----------------*- C++-*-===//
//===- KanagawaDialect.h - Definition of Kanagawa dialect -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,18 +6,18 @@
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_IBIS_IBISDIALECT_H
#define CIRCT_DIALECT_IBIS_IBISDIALECT_H
#ifndef CIRCT_DIALECT_KANAGAWA_KANAGAWADIALECT_H
#define CIRCT_DIALECT_KANAGAWA_KANAGAWADIALECT_H
#include "mlir/IR/Dialect.h"
// Pull in the dialect definition.
#include "circt/Dialect/Ibis/IbisDialect.h.inc"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h.inc"
// Pull in all enum type definitions and utility function declarations.
#include "circt/Dialect/Ibis/IbisEnums.h.inc"
#include "circt/Dialect/Kanagawa/KanagawaEnums.h.inc"
#define GET_ATTRDEF_CLASSES
#include "circt/Dialect/Ibis/IbisAttributes.h.inc"
#include "circt/Dialect/Kanagawa/KanagawaAttributes.h.inc"
#endif // CIRCT_DIALECT_IBIS_IBISDIALECT_H
#endif // CIRCT_DIALECT_KANAGAWA_KANAGAWADIALECT_H

View File

@ -1,4 +1,4 @@
//===- IbisDialect.td - Ibis dialect definition ----------------*- tablegen -*-===//
//===- KanagawaDialect.td - Kanagawa dialect definition ----*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,18 +6,18 @@
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_IBIS_DIALECT_TD
#define CIRCT_DIALECT_IBIS_DIALECT_TD
#ifndef CIRCT_DIALECT_KANAGAWA_DIALECT_TD
#define CIRCT_DIALECT_KANAGAWA_DIALECT_TD
include "mlir/IR/OpBase.td"
def IbisDialect : Dialect {
let name = "ibis";
let cppNamespace = "::circt::ibis";
def KanagawaDialect : Dialect {
let name = "kanagawa";
let cppNamespace = "::circt::kanagawa";
let summary = "Types and operations for Ibis dialect";
let summary = "Types and operations for Kanagawa dialect";
let description = [{
The `ibis` dialect is intended to support porting and eventual open sourcing
The `kanagawa` dialect is intended to support porting and eventual open sourcing
of an internal hardware development language.
}];
let useDefaultTypePrinterParser = 1;
@ -27,8 +27,8 @@ def IbisDialect : Dialect {
void registerAttributes();
}];
// Needed for ibis.pipeline_header
// Needed for kanagawa.pipeline_header
let dependentDialects = ["seq::SeqDialect", "hw::HWDialect"];
}
#endif // CIRCT_DIALECT_IBIS_DIALECT_TD
#endif // CIRCT_DIALECT_KANAGAWA_DIALECT_TD

View File

@ -1,4 +1,4 @@
//===- IbisInterfaces.td - Ibis Interfaces ---------------*- tablegen -*---===//
//===- KanagawaInterfaces.td - Kanagawa Interfaces -------*- tablegen -*---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//
//
// This describes the interfaces in the Ibis dialect.
// This describes the interfaces in the Kanagawa dialect.
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_IBIS_INTERFACES_TD
#define CIRCT_DIALECT_IBIS_INTERFACES_TD
#ifndef CIRCT_DIALECT_KANAGAWA_INTERFACES_TD
#define CIRCT_DIALECT_KANAGAWA_INTERFACES_TD
include "circt/Dialect/HW/HWOpInterfaces.td"
@ -19,7 +19,7 @@ include "mlir/IR/OpBase.td"
include "mlir/IR/SymbolInterfaces.td"
def NamedInnerSymbol : OpInterface<"NamedInnerSymbolInterface", [InnerSymbol]> {
let cppNamespace = "circt::ibis";
let cppNamespace = "circt::kanagawa";
let description = [{
An interface for operations which define inner symbols with an optional
namehint.
@ -50,7 +50,7 @@ def NamedInnerSymbol : OpInterface<"NamedInnerSymbolInterface", [InnerSymbol]> {
}
def PortOpInterface : OpInterface<"PortOpInterface", [NamedInnerSymbol]> {
let cppNamespace = "circt::ibis";
let cppNamespace = "circt::kanagawa";
let description =
"An interface for operations which describe ports.";
@ -59,17 +59,17 @@ def PortOpInterface : OpInterface<"PortOpInterface", [NamedInnerSymbol]> {
"Returns the data type of the port.",
"mlir::Type", "getPortType">,
InterfaceMethod<
"Returns the `!ibis.portref` value defined by the op",
"Returns the `!kanagawa.portref` value defined by the op",
"mlir::TypedValue<PortRefType>", "getPort"
>
];
}
def ScopeOpInterface : OpInterface<"ScopeOpInterface", [NamedInnerSymbol]> {
let cppNamespace = "circt::ibis";
let cppNamespace = "circt::kanagawa";
let description = [{
An interface for operations which define Ibis scopes, that can be referenced
by an `ibis.this` operation.
An interface for operations which define Kanagawa scopes, that can be referenced
by an `kanagawa.this` operation.
}];
let verify = "return detail::verifyScopeOpInterface($_op);";
@ -125,20 +125,20 @@ def ScopeOpInterface : OpInterface<"ScopeOpInterface", [NamedInnerSymbol]> {
>,
InterfaceMethod<
"Lookup a port in the scope",
"ibis::PortOpInterface", "lookupPort",
"kanagawa::PortOpInterface", "lookupPort",
(ins "llvm::StringRef":$portName),
[{}],
[{
return dyn_cast_or_null<ibis::PortOpInterface>(this->lookupInnerSym(portName));
return dyn_cast_or_null<kanagawa::PortOpInterface>(this->lookupInnerSym(portName));
}]
>
];
}
def BlockOpInterface : OpInterface<"BlockOpInterface"> {
let cppNamespace = "circt::ibis";
let cppNamespace = "circt::kanagawa";
let description = [{
An interface for Ibis block-like operations.
An interface for Kanagawa block-like operations.
}];
let methods = [
@ -150,11 +150,11 @@ def BlockOpInterface : OpInterface<"BlockOpInterface"> {
}
def MethodLikeOpInterface : OpInterface<"MethodLikeOpInterface"> {
let cppNamespace = "circt::ibis";
let cppNamespace = "circt::kanagawa";
let description = [{
An interface for Ibis operations that act like callable methods.
An interface for Kanagawa operations that act like callable methods.
This partially implements similar functionality to the FunctionLike interface
which cannot be used for Ibis Methods due to Ibis methods defining InnerSym's
which cannot be used for Kanagawa Methods due to Kanagawa methods defining InnerSym's
whereas the FunctionLike interface is built on the assumption of the function
defining a Symbol (i.e. inherits from the Symbol interface).
}];
@ -199,4 +199,4 @@ def MethodLikeOpInterface : OpInterface<"MethodLikeOpInterface"> {
}];
}
#endif // CIRCT_DIALECT_IBIS_INTERFACES_TD
#endif // CIRCT_DIALECT_KANAGAWA_INTERFACES_TD

View File

@ -1,4 +1,4 @@
//===- IbisOps.h - Definition of Ibis dialect ops ----------------*- C++-*-===//
//===- KanagawaOps.h - Definition of Kanagawa dialect ops -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,14 +6,14 @@
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_IBIS_IBISOPS_H
#define CIRCT_DIALECT_IBIS_IBISOPS_H
#ifndef CIRCT_DIALECT_KANAGAWA_KANAGAWAOPS_H
#define CIRCT_DIALECT_KANAGAWA_KANAGAWAOPS_H
#include "circt/Dialect/DC/DCTypes.h"
#include "circt/Dialect/HW/HWOpInterfaces.h"
#include "circt/Dialect/Handshake/HandshakeInterfaces.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "circt/Dialect/Seq/SeqTypes.h"
#include "circt/Support/InstanceGraphInterface.h"
#include "circt/Support/LLVM.h"
@ -28,29 +28,30 @@
#include "mlir/Interfaces/InferTypeOpInterface.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
namespace circt {
namespace ibis {
namespace kanagawa {
class ContainerOp;
class ThisOp;
// Symbol name for the ibis operator library to be used during scheduling.
static constexpr const char *kIbisOperatorLibName = "ibis_operator_library";
// Symbol name for the kanagawa operator library to be used during scheduling.
static constexpr const char *kKanagawaOperatorLibName =
"kanagawa_operator_library";
namespace detail {
// Verify that `op` conforms to the ScopeOpInterface.
LogicalResult verifyScopeOpInterface(Operation *op);
// Returns the %this value of an ibis scope-defining operation. Implemented
// here to hide the dependence on `ibis.this`, which is not defined before the
// interface definition.
// Returns the %this value of an kanagawa scope-defining operation. Implemented
// here to hide the dependence on `kanagawa.this`, which is not defined before
// the interface definition.
mlir::FailureOr<mlir::TypedValue<ScopeRefType>> getThisFromScope(Operation *op);
} // namespace detail
} // namespace ibis
} // namespace kanagawa
} // namespace circt
#include "circt/Dialect/Ibis/IbisInterfaces.h.inc"
#include "circt/Dialect/Kanagawa/KanagawaInterfaces.h.inc"
#define GET_OP_CLASSES
#include "circt/Dialect/Ibis/Ibis.h.inc"
#include "circt/Dialect/Kanagawa/Kanagawa.h.inc"
#endif // CIRCT_DIALECT_IBIS_IBISOPS_H
#endif // CIRCT_DIALECT_KANAGAWA_KANAGAWAOPS_H

View File

@ -1,4 +1,4 @@
//===- IbisOps.td - Definition of Ibis dialect operations -----------------===//
//===- KanagawaOps.td - Definition of Kanagawa dialect operations ---------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_IBIS_IBISOPS_TD
#define CIRCT_DIALECT_IBIS_IBISOPS_TD
#ifndef CIRCT_DIALECT_KANAGAWA_KANAGAWAOPS_TD
#define CIRCT_DIALECT_KANAGAWA_KANAGAWAOPS_TD
include "mlir/IR/OpAsmInterface.td"
include "mlir/IR/RegionKindInterface.td"
@ -21,33 +21,33 @@ include "mlir/IR/BuiltinAttributeInterfaces.td"
include "circt/Dialect/Handshake/HandshakeInterfaces.td"
include "circt/Dialect/HW/HWAttributesNaming.td"
include "circt/Dialect/HW/HWOpInterfaces.td"
include "circt/Dialect/Ibis/IbisInterfaces.td"
include "circt/Dialect/Ibis/IbisTypes.td"
include "circt/Dialect/Kanagawa/KanagawaInterfaces.td"
include "circt/Dialect/Kanagawa/KanagawaTypes.td"
include "circt/Dialect/Handshake/HandshakeInterfaces.td"
include "circt/Dialect/Seq/SeqTypes.td"
include "circt/Support/InstanceGraphInterface.td"
include "circt/Dialect/HW/HWTypes.td"
class IbisOp<string mnemonic, list<Trait> traits = []> :
Op<IbisDialect, mnemonic, traits>;
class KanagawaOp<string mnemonic, list<Trait> traits = []> :
Op<KanagawaDialect, mnemonic, traits>;
def HasCustomSSAName :
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>;
def ClassOp : IbisOp<"class", [
def ClassOp : KanagawaOp<"class", [
IsolatedFromAbove, RegionKindInterface,
SingleBlock,
NoTerminator, ScopeOpInterface,
InstanceGraphModuleOpInterface,
HasParent<"DesignOp"> ] > {
let summary = "Ibis class";
let summary = "Kanagawa class";
let description = [{
Ibis has the notion of a class which can contain methods and member
Kanagawa has the notion of a class which can contain methods and member
variables.
In the low-level Ibis representation, the ClassOp becomes a container for
`ibis.port`s, `ibis.container`s, and contain logic for member variables.
In the low-level Kanagawa representation, the ClassOp becomes a container for
`kanagawa.port`s, `kanagawa.container`s, and contain logic for member variables.
}];
let arguments = (ins InnerSymAttr:$inner_sym, OptionalAttr<StrAttr>:$name);
@ -69,7 +69,7 @@ def ClassOp : IbisOp<"class", [
}];
}
class InstanceOpBase<string mnemonic> : IbisOp<mnemonic, [
class InstanceOpBase<string mnemonic> : KanagawaOp<mnemonic, [
DeclareOpInterfaceMethods<InnerSymbol,["getTargetResultIndex"]>,
DeclareOpInterfaceMethods<InnerRefUserOpInterface>,
InstanceGraphInstanceOpInterface,
@ -117,9 +117,9 @@ class InstanceOpBase<string mnemonic> : IbisOp<mnemonic, [
}
def InstanceOp : InstanceOpBase<"instance"> {
let summary = "Ibis class instance";
let summary = "Kanagawa class instance";
let description = [{
Instantiates an Ibis class.
Instantiates an Kanagawa class.
}];
let extraInstanceClassDeclaration = [{
@ -141,12 +141,12 @@ def InstanceOp : InstanceOpBase<"instance"> {
class MethodOpBase<string mnemonic, list<Trait> traits = []> :
IbisOp<mnemonic, !listconcat(traits, [
KanagawaOp<mnemonic, !listconcat(traits, [
IsolatedFromAbove,
DeclareOpInterfaceMethods<InnerSymbol,["getTargetResultIndex"]>,
// FunctionOpInterface @mortbopet: This is very much a function-like
// operation, but FunctionOpInterface inherits from Symbol which is
// incompatible with the fact that ibis methods define inner symbols.
// incompatible with the fact that kanagawa methods define inner symbols.
MethodLikeOpInterface,
HasParent<"ClassOp">,
])> {
@ -178,9 +178,9 @@ def MethodOp : MethodOpBase<"method", [
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmBlockArgumentNames"]>
]> {
let summary = "Ibis method";
let summary = "Kanagawa method";
let description = [{
Ibis methods are a lot like software functions: a list of named arguments
Kanagawa methods are a lot like software functions: a list of named arguments
and unnamed return values with imperative control flow.
}];
@ -188,14 +188,14 @@ def MethodOp : MethodOpBase<"method", [
}
def DataflowMethodOp : MethodOpBase<"method.df", [
SingleBlockImplicitTerminator<"ibis::ReturnOp">,
SingleBlockImplicitTerminator<"kanagawa::ReturnOp">,
RegionKindInterface,
FineGrainedDataflowRegionOpInterface
]> {
let summary = "Ibis dataflow method";
let summary = "Kanagawa dataflow method";
let description = [{
Ibis dataflow methods share the same interface as an `ibis.method` but
Kanagawa dataflow methods share the same interface as an `kanagawa.method` but
without imperative CFG-based control flow. Instead, this method implements a
graph region, and control flow is expected to be defined by dataflow operations.
}];
@ -207,10 +207,10 @@ def DataflowMethodOp : MethodOpBase<"method.df", [
}];
}
def ReturnOp : IbisOp<"return", [
def ReturnOp : KanagawaOp<"return", [
Pure, ReturnLike, Terminator,
ParentOneOf<["MethodOp", "DataflowMethodOp"]>]> {
let summary = "Ibis method terminator";
let summary = "Kanagawa method terminator";
let arguments = (ins Variadic<AnyType>:$retValues);
let assemblyFormat = "($retValues^)? attr-dict (`:` type($retValues)^)?";
@ -221,7 +221,7 @@ def ReturnOp : IbisOp<"return", [
];
}
class BlockLikeOp<string mnemonic, list<Trait> traits = []> : IbisOp<mnemonic, !listconcat(traits, [
class BlockLikeOp<string mnemonic, list<Trait> traits = []> : KanagawaOp<mnemonic, !listconcat(traits, [
SingleBlockImplicitTerminator<"BlockReturnOp">,
AutomaticAllocationScope,
BlockOpInterface])> {
@ -269,13 +269,13 @@ class HighLevelBlockLikeOp<string mnemonic, list<Trait> traits = []> : BlockLike
}
def StaticBlockOp : HighLevelBlockLikeOp<"sblock"> {
let summary = "Ibis block";
let summary = "Kanagawa block";
let description = [{
The `ibis.sblock` operation defines a block wherein a group of operations
The `kanagawa.sblock` operation defines a block wherein a group of operations
are expected to be statically scheduleable.
The operation is not isolated from above to facilitate ease of construction.
However, once a program has been constructed and lowered to a sufficient
level, the user may run `--ibis-argify-blocks` to effectively isolate the
level, the user may run `--kanagawa-argify-blocks` to effectively isolate the
block from above, by converting SSA values referenced through dominanes into
arguments of the block
@ -287,9 +287,9 @@ def StaticBlockOp : HighLevelBlockLikeOp<"sblock"> {
def IsolatedStaticBlockOp : HighLevelBlockLikeOp<"sblock.isolated", [
IsolatedFromAbove
]> {
let summary = "Ibis isolated block";
let summary = "Kanagawa isolated block";
let description = [{
The `ibis.sblock.isolated` operation is like an `ibis.sblock` operation
The `kanagawa.sblock.isolated` operation is like an `kanagawa.sblock` operation
but with an IsolatedFromAbove condition, meaning that all arguments and
results are passed through the block as arguments and results.
}];
@ -298,9 +298,9 @@ def IsolatedStaticBlockOp : HighLevelBlockLikeOp<"sblock.isolated", [
def DCBlockOp : BlockLikeOp<"sblock.dc", [
IsolatedFromAbove
]> {
let summary = "DC-interfaced Ibis block";
let summary = "DC-interfaced Kanagawa block";
let description = [{
The `ibis.sblock.dc` operation is like an `ibis.sblock` operation with
The `kanagawa.sblock.dc` operation is like an `kanagawa.sblock` operation with
a few differences, being:
1. The operation is DC-interfaced, meaning that all arguments and results
are dc-value typed.
@ -324,19 +324,19 @@ def DCBlockOp : BlockLikeOp<"sblock.dc", [
}];
}
def InlineStaticBlockBeginOp : IbisOp<"sblock.inline.begin", [
def InlineStaticBlockBeginOp : KanagawaOp<"sblock.inline.begin", [
HasParent<"MethodOp">
]> {
let summary = "Ibis inline static block begin marker";
let summary = "Kanagawa inline static block begin marker";
let description = [{
The `ibis.sblock.inline.begin` operation is a marker that indicates the
The `kanagawa.sblock.inline.begin` operation is a marker that indicates the
begin of an inline static block.
The operation is used to maintain `ibis.sblocks` while in the Ibis inline
The operation is used to maintain `kanagawa.sblocks` while in the Kanagawa inline
phase (to facilitate e.g. mem2reg).
The operation:
1. denotes the begin of the sblock
2. carries whatever attributes that the source `ibis.sblock` carried.
2. carries whatever attributes that the source `kanagawa.sblock` carried.
3. is considered side-effectfull.
}];
@ -347,14 +347,14 @@ def InlineStaticBlockBeginOp : IbisOp<"sblock.inline.begin", [
}];
}
def InlineStaticBlockEndOp : IbisOp<"sblock.inline.end", [
def InlineStaticBlockEndOp : KanagawaOp<"sblock.inline.end", [
HasParent<"MethodOp">
]> {
let summary = "Ibis inline static block end marker";
let summary = "Kanagawa inline static block end marker";
let description = [{
The `ibis.sblock.inline.end` operation is a marker that indicates the
The `kanagawa.sblock.inline.end` operation is a marker that indicates the
end of an inline static block.
The operation is used to maintain `ibis.sblocks` while in the Ibis inline
The operation is used to maintain `kanagawa.sblocks` while in the Kanagawa inline
phase (to facilitate e.g. mem2reg).
}];
@ -366,10 +366,10 @@ def InlineStaticBlockEndOp : IbisOp<"sblock.inline.end", [
}];
}
def BlockReturnOp : IbisOp<"sblock.return", [
def BlockReturnOp : KanagawaOp<"sblock.return", [
Pure, ReturnLike, Terminator,
ParentOneOf<["StaticBlockOp", "IsolatedStaticBlockOp", "DCBlockOp"]>]> {
let summary = "Ibis static block terminator";
let summary = "Kanagawa static block terminator";
let arguments = (ins Variadic<AnyType>:$retValues);
let assemblyFormat = "($retValues^)? attr-dict (`:` type($retValues)^)?";
@ -381,16 +381,16 @@ def BlockReturnOp : IbisOp<"sblock.return", [
}
def MemRefTypeAttr : TypeAttrBase<"MemRefType", "any memref type">;
def VarOp : IbisOp<"var", [
def VarOp : KanagawaOp<"var", [
DeclareOpInterfaceMethods<InnerSymbol,["getTargetResultIndex"]>
]> {
let summary = "Ibis variable definition";
let summary = "Kanagawa variable definition";
let description = [{
Defines an Ibis class member variable. The variable is typed with a
Defines an Kanagawa class member variable. The variable is typed with a
`memref.memref` type, and may define either a singleton or uni-dimensional
array of values.
`ibis.var` defines a symbol within the encompassing class scope which can
be dereferenced through a `!ibis.scoperef` value of the parent class.
`kanagawa.var` defines a symbol within the encompassing class scope which can
be dereferenced through a `!kanagawa.scoperef` value of the parent class.
}];
let arguments = (ins InnerSymAttr:$inner_sym, MemRefTypeAttr:$type);
@ -404,11 +404,11 @@ def VarOp : IbisOp<"var", [
}];
}
def GetVarOp : IbisOp<"get_var", [
def GetVarOp : KanagawaOp<"get_var", [
DeclareOpInterfaceMethods<InnerRefUserOpInterface>,
HasCustomSSAName
]> {
let summary = "Dereferences an ibis member variable through a scoperef";
let summary = "Dereferences an kanagawa member variable through a scoperef";
let arguments = (ins ScopeRefType:$instance, FlatSymbolRefAttr:$varName);
let results = (outs AnyMemRef:$var);
let assemblyFormat = [{
@ -427,13 +427,13 @@ def GetVarOp : IbisOp<"get_var", [
}];
}
def CallOp : IbisOp<"call", [
def CallOp : KanagawaOp<"call", [
DeclareOpInterfaceMethods<InnerRefUserOpInterface>,
CallOpInterface
]> {
let summary = "Ibis method call";
let summary = "Kanagawa method call";
let description = [{
Dispatch a call to an Ibis method.
Dispatch a call to an Kanagawa method.
}];
let arguments = (ins InnerRefAttr:$callee, Variadic<AnyType>:$operands);
@ -474,10 +474,10 @@ def CallOp : IbisOp<"call", [
def PathDirection : I32EnumAttr<"PathDirection", "path direction", [
I32EnumAttrCase<"Parent", 0, "parent">,
I32EnumAttrCase<"Child", 1, "child">]> {
let cppNamespace = "::circt::ibis";
let cppNamespace = "::circt::kanagawa";
}
def PathStepAttr : AttrDef<IbisDialect, "PathStep", [TypedAttrInterface]> {
def PathStepAttr : AttrDef<KanagawaDialect, "PathStep", [TypedAttrInterface]> {
let description = "Used to describe a single step in a path";
let parameters = (ins
"PathDirection":$direction,
@ -495,20 +495,20 @@ def PathStepAttr : AttrDef<IbisDialect, "PathStep", [TypedAttrInterface]> {
def PathStepArrayAttr :
TypedArrayAttrBase<PathStepAttr, "Path step array attribute">;
def PathOp : IbisOp<"path", [
def PathOp : KanagawaOp<"path", [
DeclareOpInterfaceMethods<InnerRefUserOpInterface>,
Pure, InferTypeOpInterface, HasCustomSSAName
]> {
let summary = "Ibis path";
let summary = "Kanagawa path";
let description = [{
The `ibis.path` operation describes an instance hierarchy path relative to
The `kanagawa.path` operation describes an instance hierarchy path relative to
the current scope. The path is specified by a list of either parent or
child identifiers (navigating up or down the hierarchy, respectively).
Scopes along the path are optionally typed, however, An `ibis.path` must
lways terminate in a fully typed specifier, i.e. never an `!ibis.scoperef<>`.
Scopes along the path are optionally typed, however, An `kanagawa.path` must
lways terminate in a fully typed specifier, i.e. never an `!kanagawa.scoperef<>`.
The operation returns a single `!ibis.scoperef`-typed value representing
The operation returns a single `!kanagawa.scoperef`-typed value representing
the scope at the end of the path.
}];
@ -539,11 +539,11 @@ def PathOp : IbisOp<"path", [
let hasCanonicalizeMethod = 1;
}
def ThisOp : IbisOp<"this", [
def ThisOp : KanagawaOp<"this", [
DeclareOpInterfaceMethods<InnerRefUserOpInterface>,
HasCustomSSAName
]> {
let summary = "Return a handle to the current scope `!ibis.scoperef`";
let summary = "Return a handle to the current scope `!kanagawa.scoperef`";
let arguments = (ins InnerRefAttr:$scopeName);
let results = (outs ScopeRefType:$thisRef);
@ -569,10 +569,10 @@ def ThisOp : IbisOp<"this", [
}
// ===---------------------------------------------------------------------===//
// Low-level Ibis operations
// Low-level Kanagawa operations
// ===---------------------------------------------------------------------===//
def DesignOp : IbisOp<"design", [
def DesignOp : KanagawaOp<"design", [
Symbol,
SingleBlock,
InnerSymbolTable,
@ -580,7 +580,7 @@ def DesignOp : IbisOp<"design", [
NoRegionArguments,
IsolatedFromAbove
]> {
let summary = "All Ibis containers must be inside this op";
let summary = "All Kanagawa containers must be inside this op";
let arguments = (ins SymbolNameAttr:$sym_name);
let regions = (region SizedRegion<1>:$body);
@ -590,7 +590,7 @@ def DesignOp : IbisOp<"design", [
}];
}
def ContainerOp : IbisOp<"container", [
def ContainerOp : KanagawaOp<"container", [
SingleBlock,
NoTerminator, NoRegionArguments,
ScopeOpInterface, IsolatedFromAbove,
@ -599,9 +599,9 @@ def ContainerOp : IbisOp<"container", [
DeclareOpInterfaceMethods<NamedInnerSymbol>,
ParentOneOf<["DesignOp", "ClassOp"]>
]> {
let summary = "Ibis container";
let summary = "Kanagawa container";
let description = [{
An ibis container describes a collection of logic nested within an Ibis class.
An kanagawa container describes a collection of logic nested within an Kanagawa class.
}];
let arguments = (ins InnerSymAttr:$inner_sym, UnitAttr:$isTopLevel, OptionalAttr<StrAttr>:$name);
@ -649,9 +649,9 @@ def ContainerOp : IbisOp<"container", [
}
def ContainerInstanceOp : InstanceOpBase<"container.instance"> {
let summary = "Ibis container instance";
let summary = "Kanagawa container instance";
let description = [{
Instantiates an Ibis container.
Instantiates an Kanagawa container.
}];
let extraInstanceClassDeclaration = [{
@ -672,20 +672,20 @@ def ContainerInstanceOp : InstanceOpBase<"container.instance"> {
}];
}
def GetPortOp : IbisOp<"get_port", [
def GetPortOp : KanagawaOp<"get_port", [
Pure,
DeclareOpInterfaceMethods<InnerRefUserOpInterface>,
HasCustomSSAName
]> {
let summary = "Ibis get port";
let summary = "Kanagawa get port";
let description = [{
Given an Ibis class reference, returns a port of said class. The port
Given an Kanagawa class reference, returns a port of said class. The port
is specified by the symbol name of the port in the referenced class.
Importantly, the user must specify how they intend to use the op, by
specifying the direction of the portref type that this op is generated with.
If the request port is to be read from, the type must be `!ibis.portref<out T>`
and if the port is to be written to, the type must be `!ibis.portref<in T>`.
If the request port is to be read from, the type must be `!kanagawa.portref<out T>`
and if the port is to be written to, the type must be `!kanagawa.portref<in T>`.
This is to ensure that the usage is reflected in the get_port type which in
turn is used by the tunneling passes to create the proper ports through the
hierarchy.
@ -706,7 +706,7 @@ def GetPortOp : IbisOp<"get_port", [
let builders = [
OpBuilder<(ins "Value":$instance, "StringAttr":$portName, "Type":$innerPortType,
"ibis::Direction":$direction), [{
"kanagawa::Direction":$direction), [{
build($_builder, $_state, $_builder.getType<PortRefType>(
innerPortType, direction), instance, portName
);
@ -716,7 +716,7 @@ def GetPortOp : IbisOp<"get_port", [
let hasCanonicalizeMethod = 1;
let extraClassDeclaration = [{
// Returns the direction requested by this get_port op.
ibis::Direction getDirection() {
kanagawa::Direction getDirection() {
return llvm::cast<PortRefType>(getPort().getType()).getDirection();
}
@ -726,7 +726,7 @@ def GetPortOp : IbisOp<"get_port", [
}
class PortLikeOp<string mnemonic, list<Trait> traits = []> :
IbisOp<mnemonic, !listconcat(traits, [
KanagawaOp<mnemonic, !listconcat(traits, [
PortOpInterface,
ParentOneOf<["ClassOp", "ContainerOp"]>,
InferTypeOpInterface,
@ -735,7 +735,7 @@ class PortLikeOp<string mnemonic, list<Trait> traits = []> :
])> {
let description = [{
An ibis port has an attached 'name' attribute. This is a name-hint used
An kanagawa port has an attached 'name' attribute. This is a name-hint used
to generate the final port name. The port name and port symbol are not
related, and all references to a port is done through the port symbol.
}];
@ -751,7 +751,7 @@ class PortLikeOp<string mnemonic, list<Trait> traits = []> :
return getTypeAttr().getValue();
}
static ibis::Direction getPortDirection();
static kanagawa::Direction getPortDirection();
/// Infer the return types of this operation.
static LogicalResult inferReturnTypes(MLIRContext *context,
@ -787,27 +787,27 @@ class PortLikeOp<string mnemonic, list<Trait> traits = []> :
}
def InputPortOp : PortLikeOp<"port.input"> {
let summary = "Ibis input port";
let summary = "Kanagawa input port";
let extraPortClassDefinition = [{
ibis::Direction InputPortOp::getPortDirection() {
return ibis::Direction::Input;
kanagawa::Direction InputPortOp::getPortDirection() {
return kanagawa::Direction::Input;
}
}];
}
def OutputPortOp : PortLikeOp<"port.output"> {
let summary = "Ibis output port";
let summary = "Kanagawa output port";
let extraPortClassDefinition = [{
ibis::Direction OutputPortOp::getPortDirection() {
return ibis::Direction::Output;
kanagawa::Direction OutputPortOp::getPortDirection() {
return kanagawa::Direction::Output;
}
}];
let hasCanonicalizeMethod = 1;
}
class WireLikeOp<string mnemonic, list<Trait> traits = []> :
IbisOp<mnemonic, !listconcat(traits, [
KanagawaOp<mnemonic, !listconcat(traits, [
PortOpInterface,
ParentOneOf<["ClassOp", "ContainerOp"]>,
HasCustomSSAName,
@ -819,7 +819,7 @@ class WireLikeOp<string mnemonic, list<Trait> traits = []> :
return getPort().getType();
}
static ibis::Direction getPortDirection();
static kanagawa::Direction getPortDirection();
}];
code extraWireClassDefinition = ?;
@ -833,7 +833,7 @@ class WireLikeOp<string mnemonic, list<Trait> traits = []> :
class InnerTypeToPortrefTypeConstraint<string lhs, string rhs, string dir>
: TypesMatchWith<"the rhs type dictates the inner type of the rhs portref type",
lhs, rhs, "PortRefType::get($_ctxt, $_self, ibis::Direction::" # dir # ")">;
lhs, rhs, "PortRefType::get($_ctxt, $_self, kanagawa::Direction::" # dir # ")">;
class PortRefToInnerTypeConstraint<string lhs, string rhs>
: TypesMatchWith<"the inner type of the lhs portref type dictates the rhs type",
@ -842,9 +842,9 @@ class PortRefToInnerTypeConstraint<string lhs, string rhs>
def InputWireOp : WireLikeOp<"wire.input", [
InnerTypeToPortrefTypeConstraint<"output", "port", "Input">
]> {
let summary = "Ibis input wire";
let summary = "Kanagawa input wire";
let description = [{
An input wire defines an `ibis.portref<in T>` port alongside a value
An input wire defines an `kanagawa.portref<in T>` port alongside a value
of type `T` which represents the value to-be-written to the wire.
}];
@ -855,8 +855,8 @@ def InputWireOp : WireLikeOp<"wire.input", [
}];
let extraWireClassDefinition = [{
ibis::Direction $cppClass::getPortDirection() {
return ibis::Direction::Input;
kanagawa::Direction $cppClass::getPortDirection() {
return kanagawa::Direction::Input;
}
}];
@ -864,7 +864,7 @@ def InputWireOp : WireLikeOp<"wire.input", [
OpBuilder<(ins "StringAttr":$inner_sym, "Type":$innerPortType, CArg<"mlir::StringAttr", "nullptr">:$name), [{
build($_builder, $_state,
{$_builder.getType<PortRefType>(
innerPortType, ibis::Direction::Input), innerPortType}, hw::InnerSymAttr::get(inner_sym), name);
innerPortType, kanagawa::Direction::Input), innerPortType}, hw::InnerSymAttr::get(inner_sym), name);
}]>
];
@ -874,9 +874,9 @@ def InputWireOp : WireLikeOp<"wire.input", [
def OutputWireOp : WireLikeOp<"wire.output", [
InnerTypeToPortrefTypeConstraint<"input", "port", "Output">
]> {
let summary = "Ibis output wire";
let summary = "Kanagawa output wire";
let description = [{
An output wire defines an `ibis.portref<out T>` port that can be read.
An output wire defines an `kanagawa.portref<out T>` port that can be read.
The operation takes an input value of type `T` which represents the value
on the output portref.
}];
@ -888,20 +888,20 @@ def OutputWireOp : WireLikeOp<"wire.output", [
}];
let extraWireClassDefinition = [{
ibis::Direction $cppClass::getPortDirection() {
return ibis::Direction::Output;
kanagawa::Direction $cppClass::getPortDirection() {
return kanagawa::Direction::Output;
}
}];
let hasCanonicalizeMethod = 1;
}
def PortReadOp : IbisOp<"port.read", [
def PortReadOp : KanagawaOp<"port.read", [
PortRefToInnerTypeConstraint<"port", "output">,
Pure,
HasCustomSSAName
]> {
let summary = "Ibis port read";
let summary = "Kanagawa port read";
let description = [{
Read the value of a port reference.
}];
@ -913,10 +913,10 @@ def PortReadOp : IbisOp<"port.read", [
}];
}
def PortWriteOp : IbisOp<"port.write", [
def PortWriteOp : KanagawaOp<"port.write", [
PortRefToInnerTypeConstraint<"port", "value">
]> {
let summary = "Ibis port write";
let summary = "Kanagawa port write";
let description = [{
Write a value to a port reference.
}];
@ -927,15 +927,15 @@ def PortWriteOp : IbisOp<"port.write", [
}];
}
def PipelineHeaderOp : IbisOp<"pipeline.header", [
def PipelineHeaderOp : KanagawaOp<"pipeline.header", [
Pure
]> {
let summary = "Ibis pipeline header operation";
let summary = "Kanagawa pipeline header operation";
let description = [{
This operation defines the hardware-like values used to drive a pipeline,
such as clock and reset.
This is an intermediate operation, meaning that it's strictly used to
facilitate progressive lowering of ibis static blocks to scheduled pipelines.
facilitate progressive lowering of kanagawa static blocks to scheduled pipelines.
}];
let arguments = (ins);
@ -943,4 +943,4 @@ def PipelineHeaderOp : IbisOp<"pipeline.header", [
let assemblyFormat = "attr-dict";
}
#endif // CIRCT_DIALECT_IBIS_IBISOPS_TD
#endif // CIRCT_DIALECT_KANAGAWA_KANAGAWAOPS_TD

View File

@ -0,0 +1,29 @@
//===- KanagawaPassPipelines.h - Kanagawa pass pipelines --------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_KANAGAWA_KANAGAWAPASSPIPELINES_H
#define CIRCT_DIALECT_KANAGAWA_KANAGAWAPASSPIPELINES_H
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "mlir/Pass/PassManager.h"
#include <memory>
#include <optional>
namespace circt {
namespace kanagawa {
// Loads a pass pipeline to transform low-level Kanagawa constructs.
void loadKanagawaLowLevelPassPipeline(mlir::PassManager &pm);
// Loads a pass pipeline to transform high-level Kanagawa constructs.
void loadKanagawaHighLevelPassPipeline(mlir::PassManager &pm);
} // namespace kanagawa
} // namespace circt
#endif // CIRCT_DIALECT_KANAGAWA_KANAGAWAPASSPIPELINES_H

View File

@ -1,4 +1,4 @@
//===- Passes.h - Ibis pass entry points -------------------------*- C++-*-===//
//===- Passes.h - Kanagawa pass entry points --------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_IBIS_IBISPASSES_H
#define CIRCT_DIALECT_IBIS_IBISPASSES_H
#ifndef CIRCT_DIALECT_KANAGAWA_KANAGAWAPASSES_H
#define CIRCT_DIALECT_KANAGAWA_KANAGAWAPASSES_H
#include "circt/Dialect/DC/DCDialect.h"
#include "circt/Dialect/Pipeline/PipelineDialect.h"
@ -20,15 +20,15 @@
#include <optional>
namespace circt {
namespace ibis {
namespace kanagawa {
#define GEN_PASS_DECL_IBISTUNNELING
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
#define GEN_PASS_DECL_KANAGAWATUNNELING
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
std::unique_ptr<mlir::Pass> createCallPrepPass();
std::unique_ptr<mlir::Pass> createContainerizePass();
std::unique_ptr<mlir::Pass>
createTunnelingPass(const IbisTunnelingOptions & = {});
createTunnelingPass(const KanagawaTunnelingOptions & = {});
std::unique_ptr<mlir::Pass> createPortrefLoweringPass();
std::unique_ptr<mlir::Pass> createCleanSelfdriversPass();
std::unique_ptr<mlir::Pass> createContainersToHWPass();
@ -43,9 +43,9 @@ std::unique_ptr<mlir::Pass> createAddOperatorLibraryPass();
/// Generate the code for registering passes.
#define GEN_PASS_REGISTRATION
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace ibis
} // namespace kanagawa
} // namespace circt
#endif // CIRCT_DIALECT_IBIS_IBISPASSES_H
#endif // CIRCT_DIALECT_KANAGAWA_KANAGAWAPASSES_H

View File

@ -1,4 +1,4 @@
//===-- Passes.td - Ibis pass definition file --------------*- tablegen -*-===//
//===-- Passes.td - Kanagawa pass definition file ----------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,34 +6,34 @@
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_IBIS_PASSES_TD
#define CIRCT_DIALECT_IBIS_PASSES_TD
#ifndef CIRCT_DIALECT_KANAGAWA_PASSES_TD
#define CIRCT_DIALECT_KANAGAWA_PASSES_TD
include "mlir/Pass/PassBase.td"
def IbisCallPrep : Pass<"ibis-call-prep", "DesignOp"> {
let summary = "Convert ibis method calls to use `dc.value`";
def KanagawaCallPrep : Pass<"kanagawa-call-prep", "DesignOp"> {
let summary = "Convert kanagawa method calls to use `dc.value`";
let constructor = "::circt::ibis::createCallPrepPass()";
let constructor = "::circt::kanagawa::createCallPrepPass()";
let dependentDialects = [
"::circt::hw::HWDialect"];
}
def IbisContainerize : Pass<"ibis-containerize", "DesignOp"> {
let summary = "Ibis containerization pass";
def KanagawaContainerize : Pass<"kanagawa-containerize", "DesignOp"> {
let summary = "Kanagawa containerization pass";
let description = [{
Convert Ibis classes to containers, and outlines containers inside classes.
Convert Kanagawa classes to containers, and outlines containers inside classes.
}];
let constructor = "::circt::ibis::createContainerizePass()";
let constructor = "::circt::kanagawa::createContainerizePass()";
}
def IbisTunneling : Pass<"ibis-tunneling", "DesignOp"> {
let summary = "Ibis tunneling pass";
def KanagawaTunneling : Pass<"kanagawa-tunneling", "DesignOp"> {
let summary = "Kanagawa tunneling pass";
let description = [{
Tunnels relative `get_port` ops through the module hierarchy, based on
`ibis.path` ops. The result of this pass is that various new in- and output
ports of `!ibis.portref<...>` type are created.
`kanagawa.path` ops. The result of this pass is that various new in- and output
ports of `!kanagawa.portref<...>` type are created.
After this pass, `get_port` ops should only exist at the same scope of
container instantiations.
@ -44,7 +44,7 @@ def IbisTunneling : Pass<"ibis-tunneling", "DesignOp"> {
write accesses, and the suffixes must be different (in this case, the suffixes
will be appended to the target port name, and thus de-alias the resulting ports).
}];
let constructor = "::circt::ibis::createTunnelingPass()";
let constructor = "::circt::kanagawa::createTunnelingPass()";
let options = [
Option<"readSuffix", "read-suffix", "std::string", "\".rd\"",
"Suffix to be used for the port when a port is tunneled for read access">,
@ -53,10 +53,10 @@ def IbisTunneling : Pass<"ibis-tunneling", "DesignOp"> {
];
}
def IbisPortrefLowering : Pass<"ibis-lower-portrefs", "::mlir::ModuleOp"> {
let summary = "Ibis portref lowering pass";
def KanagawaPortrefLowering : Pass<"kanagawa-lower-portrefs", "::mlir::ModuleOp"> {
let summary = "Kanagawa portref lowering pass";
let description = [{
Lower `ibis.portref<portref <T>>` to T (i.e. portref resolution).
Lower `kanagawa.portref<portref <T>>` to T (i.e. portref resolution).
We do this by analyzing how a portref is used
inside a container, and then creating an in- or output port based on that.
@ -75,48 +75,48 @@ def IbisPortrefLowering : Pass<"ibis-lower-portrefs", "::mlir::ModuleOp"> {
the outside.
A benefit of having portref lowering separate from portref tunneling is that
portref lowering can be done on an `ibis.container` granularity, allowing
portref lowering can be done on an `kanagawa.container` granularity, allowing
for a bit of parallelism in the flow.
}];
let constructor = "::circt::ibis::createPortrefLoweringPass()";
let constructor = "::circt::kanagawa::createPortrefLoweringPass()";
}
def IbisCleanSelfdrivers : Pass<"ibis-clean-selfdrivers", "DesignOp"> {
let summary = "Ibis clean selfdrivers pass";
def KanagawaCleanSelfdrivers : Pass<"kanagawa-clean-selfdrivers", "DesignOp"> {
let summary = "Kanagawa clean selfdrivers pass";
let description = [{
- Removes `ibis.port.input`s which are driven by operations within the same
- Removes `kanagawa.port.input`s which are driven by operations within the same
container.
- Removes reads of instance ports which are also written to within the same
container.
}];
let constructor = "::circt::ibis::createCleanSelfdriversPass()";
let constructor = "::circt::kanagawa::createCleanSelfdriversPass()";
let dependentDialects = ["::circt::hw::HWDialect"];
}
def IbisContainersToHW : Pass<"ibis-convert-containers-to-hw", "::mlir::ModuleOp"> {
let summary = "Ibis containers to hw conversion pass";
def KanagawaContainersToHW : Pass<"kanagawa-convert-containers-to-hw", "::mlir::ModuleOp"> {
let summary = "Kanagawa containers to hw conversion pass";
let description = [{
Converts `ibis.container` ops to `hw.module` ops.
Converts `kanagawa.container` ops to `hw.module` ops.
}];
let constructor = "::circt::ibis::createContainersToHWPass()";
let constructor = "::circt::kanagawa::createContainersToHWPass()";
let dependentDialects = ["::circt::hw::HWDialect"];
}
def IbisArgifyBlocks : Pass<"ibis-argify-blocks"> {
let summary = "Add arguments to ibis blocks";
def KanagawaArgifyBlocks : Pass<"kanagawa-argify-blocks"> {
let summary = "Add arguments to kanagawa blocks";
let description = [{
Analyses `ibis.sblock` operations and converts any SSA value defined outside
the `ibis.sblock` to a block argument. As a result, `ibis.sblock.isolated`
Analyses `kanagawa.sblock` operations and converts any SSA value defined outside
the `kanagawa.sblock` to a block argument. As a result, `kanagawa.sblock.isolated`
are produced.
}];
let constructor = "::circt::ibis::createArgifyBlocksPass()";
let constructor = "::circt::kanagawa::createArgifyBlocksPass()";
}
def IbisReblock : Pass<"ibis-reblock", "ibis::MethodOp"> {
let summary = "Recreates `ibis.sblock` operations from a CFG";
def KanagawaReblock : Pass<"kanagawa-reblock", "kanagawa::MethodOp"> {
let summary = "Recreates `kanagawa.sblock` operations from a CFG";
let description = [{
Recreates `ibis.sblock` operations from a CFG. Any `ibis.block.attributes`
Recreates `kanagawa.sblock` operations from a CFG. Any `kanagawa.block.attributes`
operations at the parent operation will be added to the resulting blocks.
The IR is expected to be in maximal SSA form prior to this pass, given that
@ -124,7 +124,7 @@ def IbisReblock : Pass<"ibis-reblock", "ibis::MethodOp"> {
values that are generated within the block. Maximum SSA form thus ensures
that any value defined within the block is never used outside of the block.
It is expected that `ibis.call` operations have been isolated into
It is expected that `kanagawa.call` operations have been isolated into
their own basic blocks before this pass is run. This implies that all
operations within a block (except for the terminator operation) can be
statically scheduled with each other.
@ -140,54 +140,54 @@ def IbisReblock : Pass<"ibis-reblock", "ibis::MethodOp"> {
becomes
```mlir
^bb_foo(%arg0 : i32, %arg1 : i32):
%v_outer = ibis.sblock(%a0 : i32 = %arg0, %a1 : i32 = %arg1) -> (i32) {
%v_outer = kanagawa.sblock(%a0 : i32 = %arg0, %a1 : i32 = %arg1) -> (i32) {
%res = arith.addi %arg0, %arg1 : i32
%v = ...
ibis.sblock.return %v : i32
kanagawa.sblock.return %v : i32
}
cf.br ^bb_bar(%v_outer : i32)
```
}];
let constructor = "::circt::ibis::createReblockPass()";
let constructor = "::circt::kanagawa::createReblockPass()";
}
def IbisInlineSBlocks : Pass<"ibis-inline-sblocks", "ibis::MethodOp"> {
let summary = "Inlines `ibis.sblock` operations as MLIR blocks";
def KanagawaInlineSBlocks : Pass<"kanagawa-inline-sblocks", "kanagawa::MethodOp"> {
let summary = "Inlines `kanagawa.sblock` operations as MLIR blocks";
let description = [{
Inlines `ibis.sblock` operations, by creating MLIR blocks and `cf`
Inlines `kanagawa.sblock` operations, by creating MLIR blocks and `cf`
operations, while adding attributes to the parent operation about
`sblock`-specific attributes.
The parent attributes are located under the `ibis.blockinfo` identifier as
The parent attributes are located under the `kanagawa.blockinfo` identifier as
a dictionary attribute.
Each entry in the dictionary consists of:
- Key: an ID (numerical) string identifying the block.
- Value: a dictionary of attributes. As a minimum this will contain a
`loc`-keyed attribute specifying the location of the block.
}];
let constructor = "::circt::ibis::createInlineSBlocksPass()";
let constructor = "::circt::kanagawa::createInlineSBlocksPass()";
let dependentDialects = ["::mlir::cf::ControlFlowDialect"];
}
def IbisConvertCFToHandshake : Pass<"ibis-convert-cf-to-handshake", "ibis::ClassOp"> {
let summary = "Converts an `ibis.method` to `ibis.method.df`";
def KanagawaConvertCFToHandshake : Pass<"kanagawa-convert-cf-to-handshake", "kanagawa::ClassOp"> {
let summary = "Converts an `kanagawa.method` to `kanagawa.method.df`";
let description = [{
Converts an `ibis.method` from using `cf` operations and MLIR blocks to
an `ibis.method.df` operation, using the `handshake` dialect to represent
Converts an `kanagawa.method` from using `cf` operations and MLIR blocks to
an `kanagawa.method.df` operation, using the `handshake` dialect to represent
control flow through the `handshake` fine grained dataflow operations.
}];
let constructor = "::circt::ibis::createConvertCFToHandshakePass()";
let constructor = "::circt::kanagawa::createConvertCFToHandshakePass()";
let dependentDialects = ["::circt::handshake::HandshakeDialect", "::mlir::cf::ControlFlowDialect"];
}
def IbisConvertHandshakeToDC : Pass<"ibis-convert-handshake-to-dc", "ibis::ClassOp"> {
let summary = "Converts an `ibis.method.df` to use DC";
def KanagawaConvertHandshakeToDC : Pass<"kanagawa-convert-handshake-to-dc", "kanagawa::ClassOp"> {
let summary = "Converts an `kanagawa.method.df` to use DC";
let description = [{
Converts an `ibis.method.df` from using `handshake` operations to
Converts an `kanagawa.method.df` from using `handshake` operations to
`dc` operations.
}];
let constructor = "::circt::ibis::createConvertHandshakeToDCPass()";
let constructor = "::circt::kanagawa::createConvertHandshakeToDCPass()";
let dependentDialects = [
"::circt::dc::DCDialect",
"::circt::handshake::HandshakeDialect",
@ -195,31 +195,31 @@ def IbisConvertHandshakeToDC : Pass<"ibis-convert-handshake-to-dc", "ibis::Class
];
}
def IbisPrepareScheduling : Pass<"ibis-prepare-scheduling", "ibis::IsolatedStaticBlockOp"> {
let summary = "Prepare `ibis.sblock` operations for scheduling";
def KanagawaPrepareScheduling : Pass<"kanagawa-prepare-scheduling", "kanagawa::IsolatedStaticBlockOp"> {
let summary = "Prepare `kanagawa.sblock` operations for scheduling";
let description = [{
Prepares `ibis.sblock` operations for scheduling by:
- creating an `ibis.pipleine.header` operation
- moving operations of an `ibis.sblock` into a `pipeline.unscheduled`
Prepares `kanagawa.sblock` operations for scheduling by:
- creating an `kanagawa.pipleine.header` operation
- moving operations of an `kanagawa.sblock` into a `pipeline.unscheduled`
operation, which is connected to the pipeline header.
}];
let constructor = "::circt::ibis::createPrepareSchedulingPass()";
let constructor = "::circt::kanagawa::createPrepareSchedulingPass()";
let dependentDialects = ["::circt::pipeline::PipelineDialect"];
}
def IbisConvertMethodsToContainers : Pass<"ibis-convert-methods-to-containers", "ibis::ClassOp"> {
let summary = "Converts `ibis.method.df` to `ibis.container`s";
let constructor = "::circt::ibis::createConvertMethodsToContainersPass()";
def KanagawaConvertMethodsToContainers : Pass<"kanagawa-convert-methods-to-containers", "kanagawa::ClassOp"> {
let summary = "Converts `kanagawa.method.df` to `kanagawa.container`s";
let constructor = "::circt::kanagawa::createConvertMethodsToContainersPass()";
}
def IbisAddOperatorLibrary : Pass<"ibis-add-operator-library", "::mlir::ModuleOp"> {
let summary = "Injects the Ibis operator library into the IR";
def KanagawaAddOperatorLibrary : Pass<"kanagawa-add-operator-library", "::mlir::ModuleOp"> {
let summary = "Injects the Kanagawa operator library into the IR";
let description = [{
Injects the Ibis operator library into the IR, which contains the
definitions of the Ibis operators.
Injects the Kanagawa operator library into the IR, which contains the
definitions of the Kanagawa operators.
}];
let constructor = "::circt::ibis::createAddOperatorLibraryPass()";
let constructor = "::circt::kanagawa::createAddOperatorLibraryPass()";
let dependentDialects = ["::circt::ssp::SSPDialect"];
}
#endif // CIRCT_DIALECT_IBIS_PASSES_TD
#endif // CIRCT_DIALECT_KANAGAWA_PASSES_TD

View File

@ -1,4 +1,4 @@
//===- IbisTypes.h - Definition of Ibis dialect types ------------*- C++-*-===//
//===- KanagawaTypes.h - Definition of Kanagawa dialect types ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,24 +6,24 @@
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_IBIS_IBISTYPES_H
#define CIRCT_DIALECT_IBIS_IBISTYPES_H
#ifndef CIRCT_DIALECT_KANAGAWA_KANAGAWATYPES_H
#define CIRCT_DIALECT_KANAGAWA_KANAGAWATYPES_H
#include "circt/Dialect/HW/HWAttributes.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Support/LLVM.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Types.h"
namespace circt {
namespace ibis {
// Returns true if the given type is an opaque reference to an ibis class.
namespace kanagawa {
// Returns true if the given type is an opaque reference to an kanagawa class.
bool isOpaqueScopeRefType(mlir::Type type);
} // namespace ibis
} // namespace kanagawa
} // namespace circt
#define GET_TYPEDEF_CLASSES
#include "circt/Dialect/Ibis/IbisTypes.h.inc"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h.inc"
#endif // CIRCT_DIALECT_IBIS_IBISTYPES_H
#endif // CIRCT_DIALECT_KANAGAWA_KANAGAWATYPES_H

View File

@ -1,4 +1,4 @@
//===- IbisTypes.td - Definition of Ibis dialect types --------------------===//
//===- KanagawaTypes.td - Definition of Kanagawa dialect types ------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,19 +6,19 @@
//
//===----------------------------------------------------------------------===//
#ifndef CIRCT_DIALECT_IBIS_IBISTYPES_TD
#define CIRCT_DIALECT_IBIS_IBISTYPES_TD
#ifndef CIRCT_DIALECT_KANAGAWA_KANAGAWATYPES_TD
#define CIRCT_DIALECT_KANAGAWA_KANAGAWATYPES_TD
include "circt/Dialect/Ibis/IbisDialect.td"
include "circt/Dialect/Kanagawa/KanagawaDialect.td"
include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/EnumAttr.td"
class IbisTypeDef<string name> : TypeDef<IbisDialect, name> { }
class KanagawaTypeDef<string name> : TypeDef<KanagawaDialect, name> { }
def ScopeRefType : IbisTypeDef<"ScopeRef"> {
def ScopeRefType : KanagawaTypeDef<"ScopeRef"> {
let mnemonic = "scoperef";
let description = [{
A reference to an Ibis scope. May be either a reference to a specific
A reference to an Kanagawa scope. May be either a reference to a specific
scope (given a `$scopeName` argument) or an opaque reference.
}];
@ -39,30 +39,30 @@ def ScopeRefType : IbisTypeDef<"ScopeRef"> {
}
def AnyScopeRefType : Type<
CPred<"llvm::isa<ibis::ScopeRefType>($_self)">,
CPred<"llvm::isa<kanagawa::ScopeRefType>($_self)">,
"must be a !dc.classref<T?> type",
"ibis::ScopeRefType">{
"kanagawa::ScopeRefType">{
}
def OpaqueScopeRefType : Type<
CPred<"ibis::isOpaqueScopeRefType($_self)">,
CPred<"kanagawa::isOpaqueScopeRefType($_self)">,
"must be a !dc.classref<> type">,
BuildableType<"$_builder.getType<ibis::ScopeRefType>()"> {
BuildableType<"$_builder.getType<kanagawa::ScopeRefType>()"> {
}
def Input : I32EnumAttrCase<"Input", 0, "in">;
def Output : I32EnumAttrCase<"Output", 1, "out">;
def Direction : I32EnumAttr<"Direction", "Ibis port direction",
def Direction : I32EnumAttr<"Direction", "Kanagawa port direction",
[Input, Output]> {
let cppNamespace = "::circt::ibis";
let cppNamespace = "::circt::kanagawa";
}
def PortRefType : IbisTypeDef<"PortRef"> {
def PortRefType : KanagawaTypeDef<"PortRef"> {
let mnemonic = "portref";
let parameters = (ins "TypeAttr":$portTypeAttr, "ibis::Direction":$direction);
let parameters = (ins "TypeAttr":$portTypeAttr, "kanagawa::Direction":$direction);
let assemblyFormat = "`<` $direction $portTypeAttr `>`";
let description = [{
A reference to an Ibis port.
A reference to an Kanagawa port.
}];
let extraClassDeclaration = [{
@ -72,10 +72,10 @@ def PortRefType : IbisTypeDef<"PortRef"> {
}];
let builders = [
TypeBuilder<(ins "Type":$t, "ibis::Direction":$d), [{
TypeBuilder<(ins "Type":$t, "kanagawa::Direction":$d), [{
return $_get($_ctxt, TypeAttr::get(t), d);
}]>
];
}
#endif // CIRCT_DIALECT_IBIS_IBISTYPES_TD
#endif // CIRCT_DIALECT_KANAGAWA_KANAGAWATYPES_TD

View File

@ -28,8 +28,8 @@
#include "circt/Dialect/HW/HWDialect.h"
#include "circt/Dialect/HWArith/HWArithDialect.h"
#include "circt/Dialect/Handshake/HandshakeDialect.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Interop/InteropDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/LLHD/IR/LLHDDialect.h"
#include "circt/Dialect/LTL/LTLDialect.h"
#include "circt/Dialect/LoopSchedule/LoopScheduleDialect.h"
@ -71,7 +71,7 @@ inline void registerAllDialects(mlir::DialectRegistry &registry) {
hw::HWDialect,
hwarith::HWArithDialect,
interop::InteropDialect,
ibis::IbisDialect,
kanagawa::KanagawaDialect,
llhd::LLHDDialect,
loopschedule::LoopScheduleDialect,
ltl::LTLDialect,

View File

@ -26,7 +26,7 @@
#include "circt/Dialect/FSM/FSMPasses.h"
#include "circt/Dialect/HW/HWPasses.h"
#include "circt/Dialect/Handshake/HandshakePasses.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/LLHD/Transforms/Passes.h"
#include "circt/Dialect/MSFT/MSFTPasses.h"
#include "circt/Dialect/Moore/MoorePasses.h"
@ -72,7 +72,7 @@ inline void registerAllPasses() {
seq::registerPasses();
sv::registerPasses();
handshake::registerPasses();
ibis::registerPasses();
kanagawa::registerPasses();
hw::registerPasses();
pipeline::registerPasses();
sim::registerPasses();

View File

@ -14,7 +14,7 @@ set(CIRCT_INTEGRATION_TEST_DEPENDS
circt-test-runners
firtool
hlstool
ibistool
kanagawatool
handshake-runner
)

View File

@ -1,51 +1,51 @@
// XFAIL: *
// See https://github.com/llvm/circt/issues/6658
// RUN: ibistool -lo %s
// RUN: kanagawatool -lo %s
ibis.design @foo {
kanagawa.design @foo {
// A class hierarchy with a shared parent, and accessing between the children
ibis.class sym @C1 {
%this = ibis.this <@foo::@C1>
%out = ibis.port.output "out" sym @out : i32
kanagawa.class sym @C1 {
%this = kanagawa.this <@foo::@C1>
%out = kanagawa.port.output "out" sym @out : i32
%c0 = hw.constant 42 : i32
ibis.port.write %out, %c0 : !ibis.portref<out i32>
kanagawa.port.write %out, %c0 : !kanagawa.portref<out i32>
}
ibis.class sym @C2 {
%this = ibis.this <@foo::@C2>
kanagawa.class sym @C2 {
%this = kanagawa.this <@foo::@C2>
%go_port = ibis.port.input "go" sym @go : i1
%clk_port = ibis.port.input "clk" sym @clk : !seq.clock
%rst_port = ibis.port.input "rst" sym @rst : i1
%done_port = ibis.port.output "done" sym @done : i1
%out_port = ibis.port.output "out" sym @out : i32
%go_port = kanagawa.port.input "go" sym @go : i1
%clk_port = kanagawa.port.input "clk" sym @clk : !seq.clock
%rst_port = kanagawa.port.input "rst" sym @rst : i1
%done_port = kanagawa.port.output "done" sym @done : i1
%out_port = kanagawa.port.output "out" sym @out : i32
ibis.container sym @MyMethod {
%t = ibis.this <@foo::@MyMethod>
kanagawa.container sym @MyMethod {
%t = kanagawa.this <@foo::@MyMethod>
// Grab parent go, clk, reset inputs - note that the requested direction of
// these are flipped wrt. the defined direction of the ports. The semantics
// are now that get_port defines the intended usage of the port (in => i'll write to the port, out => i'll read from the port).
%parent = ibis.path [
#ibis.step<parent : !ibis.scoperef<@foo::@C2>>
%parent = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef<@foo::@C2>>
]
%go_ref = ibis.get_port %parent, @go : !ibis.scoperef<@foo::@C2> -> !ibis.portref<out i1>
%go = ibis.port.read %go_ref : !ibis.portref<out i1>
%clk_ref = ibis.get_port %parent, @clk : !ibis.scoperef<@foo::@C2> -> !ibis.portref<out !seq.clock>
%clk = ibis.port.read %clk_ref : !ibis.portref<out !seq.clock>
%rst_ref = ibis.get_port %parent, @rst : !ibis.scoperef<@foo::@C2> -> !ibis.portref<out i1>
%rst = ibis.port.read %rst_ref : !ibis.portref<out i1>
%go_ref = kanagawa.get_port %parent, @go : !kanagawa.scoperef<@foo::@C2> -> !kanagawa.portref<out i1>
%go = kanagawa.port.read %go_ref : !kanagawa.portref<out i1>
%clk_ref = kanagawa.get_port %parent, @clk : !kanagawa.scoperef<@foo::@C2> -> !kanagawa.portref<out !seq.clock>
%clk = kanagawa.port.read %clk_ref : !kanagawa.portref<out !seq.clock>
%rst_ref = kanagawa.get_port %parent, @rst : !kanagawa.scoperef<@foo::@C2> -> !kanagawa.portref<out i1>
%rst = kanagawa.port.read %rst_ref : !kanagawa.portref<out i1>
// Grab sibling c1's output
%sibling = ibis.path [
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<child , @c1 : !ibis.scoperef<@foo::@C1>>
%sibling = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<child , @c1 : !kanagawa.scoperef<@foo::@C1>>
]
%sibling_out_ref = ibis.get_port %sibling, @out : !ibis.scoperef<@foo::@C1> -> !ibis.portref<out i32>
%sibling_out = ibis.port.read %sibling_out_ref : !ibis.portref<out i32>
%sibling_out_ref = kanagawa.get_port %sibling, @out : !kanagawa.scoperef<@foo::@C1> -> !kanagawa.portref<out i32>
%sibling_out = kanagawa.port.read %sibling_out_ref : !kanagawa.portref<out i32>
%res, %done = pipeline.scheduled(%a0 : i32 = %sibling_out) clock(%clk) reset(%rst) go(%go) entryEn(%s0_enable) -> (out : i32) {
%0 = comb.mul %a0, %a0 : i32
@ -61,45 +61,45 @@ ibis.class sym @C2 {
}
// Assign parent done port and output
%parent_done_ref = ibis.get_port %parent, @done : !ibis.scoperef<@foo::@C2> -> !ibis.portref<in i1>
ibis.port.write %parent_done_ref, %done : !ibis.portref<in i1>
%parent_out_ref = ibis.get_port %parent, @out : !ibis.scoperef<@foo::@C2> -> !ibis.portref<in i32>
ibis.port.write %parent_out_ref, %res : !ibis.portref<in i32>
%parent_done_ref = kanagawa.get_port %parent, @done : !kanagawa.scoperef<@foo::@C2> -> !kanagawa.portref<in i1>
kanagawa.port.write %parent_done_ref, %done : !kanagawa.portref<in i1>
%parent_out_ref = kanagawa.get_port %parent, @out : !kanagawa.scoperef<@foo::@C2> -> !kanagawa.portref<in i32>
kanagawa.port.write %parent_out_ref, %res : !kanagawa.portref<in i32>
}
}
ibis.class sym @Parent {
%this = ibis.this <@foo::@Parent>
%c1 = ibis.instance @c1, <@foo::@C1>
%c2 = ibis.instance @c2, <@foo::@C2>
kanagawa.class sym @Parent {
%this = kanagawa.this <@foo::@Parent>
%c1 = kanagawa.instance @c1, <@foo::@C1>
%c2 = kanagawa.instance @c2, <@foo::@C2>
%go = ibis.port.input "go" sym @go : i1
%clk = ibis.port.input "clk" sym @clk : !seq.clock
%rst = ibis.port.input "rst" sym @rst : i1
%go = kanagawa.port.input "go" sym @go : i1
%clk = kanagawa.port.input "clk" sym @clk : !seq.clock
%rst = kanagawa.port.input "rst" sym @rst : i1
%done = ibis.port.output "done" sym @done : i1
%out = ibis.port.output "out" sym @out : i32
%done = kanagawa.port.output "done" sym @done : i1
%out = kanagawa.port.output "out" sym @out : i32
// Wire up to c2
%go_ref = ibis.get_port %c2, @go : !ibis.scoperef<@foo::@C2> -> !ibis.portref<in i1>
%go_val = ibis.port.read %go : !ibis.portref<in i1>
ibis.port.write %go_ref, %go_val : !ibis.portref<in i1>
%go_ref = kanagawa.get_port %c2, @go : !kanagawa.scoperef<@foo::@C2> -> !kanagawa.portref<in i1>
%go_val = kanagawa.port.read %go : !kanagawa.portref<in i1>
kanagawa.port.write %go_ref, %go_val : !kanagawa.portref<in i1>
%clk_ref = ibis.get_port %c2, @clk : !ibis.scoperef<@foo::@C2> -> !ibis.portref<in !seq.clock>
%clk_val = ibis.port.read %clk : !ibis.portref<in !seq.clock>
ibis.port.write %clk_ref, %clk_val : !ibis.portref<in !seq.clock>
%clk_ref = kanagawa.get_port %c2, @clk : !kanagawa.scoperef<@foo::@C2> -> !kanagawa.portref<in !seq.clock>
%clk_val = kanagawa.port.read %clk : !kanagawa.portref<in !seq.clock>
kanagawa.port.write %clk_ref, %clk_val : !kanagawa.portref<in !seq.clock>
%rst_ref = ibis.get_port %c2, @rst : !ibis.scoperef<@foo::@C2> -> !ibis.portref<in i1>
%rst_val = ibis.port.read %rst : !ibis.portref<in i1>
ibis.port.write %rst_ref, %rst_val : !ibis.portref<in i1>
%rst_ref = kanagawa.get_port %c2, @rst : !kanagawa.scoperef<@foo::@C2> -> !kanagawa.portref<in i1>
%rst_val = kanagawa.port.read %rst : !kanagawa.portref<in i1>
kanagawa.port.write %rst_ref, %rst_val : !kanagawa.portref<in i1>
%done_ref = ibis.get_port %c2, @done : !ibis.scoperef<@foo::@C2> -> !ibis.portref<out i1>
%done_val = ibis.port.read %done_ref : !ibis.portref<out i1>
ibis.port.write %done, %done_val : !ibis.portref<out i1>
%done_ref = kanagawa.get_port %c2, @done : !kanagawa.scoperef<@foo::@C2> -> !kanagawa.portref<out i1>
%done_val = kanagawa.port.read %done_ref : !kanagawa.portref<out i1>
kanagawa.port.write %done, %done_val : !kanagawa.portref<out i1>
%out_ref = ibis.get_port %c2, @out : !ibis.scoperef<@foo::@C2> -> !ibis.portref<out i32>
%out_val = ibis.port.read %out_ref : !ibis.portref<out i32>
ibis.port.write %out, %out_val : !ibis.portref<out i32>
%out_ref = kanagawa.get_port %c2, @out : !kanagawa.scoperef<@foo::@C2> -> !kanagawa.portref<out i32>
%out_val = kanagawa.port.read %out_ref : !kanagawa.portref<out i32>
kanagawa.port.write %out, %out_val : !kanagawa.portref<out i32>
}
}

View File

@ -79,7 +79,7 @@ tool_dirs = [
]
tools = [
'arcilator', 'circt-opt', 'circt-translate', 'firtool', 'circt-rtl-sim.py',
'equiv-rtl.sh', 'handshake-runner', 'hlstool', 'ibistool', 'circt-lec',
'equiv-rtl.sh', 'handshake-runner', 'hlstool', 'kanagawatool', 'circt-lec',
'circt-bmc', 'circt-test', 'circt-test-runner-sby.py'
]

View File

@ -22,7 +22,7 @@ add_subdirectory(FSM)
add_subdirectory(Handshake)
add_subdirectory(HW)
add_subdirectory(HWArith)
add_subdirectory(Ibis)
add_subdirectory(Kanagawa)
add_subdirectory(Interop)
add_subdirectory(LLHD)
add_subdirectory(LoopSchedule)

View File

@ -1,16 +0,0 @@
add_circt_dialect_library(CIRCTIbis
IbisDialect.cpp
IbisOps.cpp
IbisTypes.cpp
DEPENDS
MLIRIbisIncGen
LINK_LIBS PUBLIC
MLIRIR
CIRCTHW
CIRCTDC
CIRCTSeq
)
add_subdirectory(Transforms)

View File

@ -1,36 +0,0 @@
add_circt_dialect_library(CIRCTIbisTransforms
IbisCallPrep.cpp
IbisContainerize.cpp
IbisTunneling.cpp
IbisPortrefLowering.cpp
IbisCleanSelfdrivers.cpp
IbisContainersToHW.cpp
IbisArgifyBlocksPass.cpp
IbisReblockPass.cpp
IbisInlineSBlocksPass.cpp
IbisConvertCFToHandshake.cpp
IbisPassPipelines.cpp
IbisPrepareScheduling.cpp
IbisConvertHandshakeToDC.cpp
IbisMethodsToContainers.cpp
IbisAddOperatorLibrary.cpp
DEPENDS
CIRCTIbisTransformsIncGen
LINK_LIBS PUBLIC
CIRCTDC
CIRCTHandshake
CIRCTPipelineOps
CIRCTCFToHandshake
CIRCTHandshakeToDC
CIRCTIbis
CIRCTSSP
CIRCTHW
CIRCTHWTransforms
CIRCTSupport
CIRCTTransforms
MLIRIR
MLIRPass
MLIRTransformUtils
)

View File

@ -0,0 +1,16 @@
add_circt_dialect_library(CIRCTKanagawa
KanagawaDialect.cpp
KanagawaOps.cpp
KanagawaTypes.cpp
DEPENDS
MLIRKanagawaIncGen
LINK_LIBS PUBLIC
MLIRIR
CIRCTHW
CIRCTDC
CIRCTSeq
)
add_subdirectory(Transforms)

View File

@ -1,4 +1,4 @@
//===- IbisDialect.cpp - Implementation of Ibis dialect -------------------===//
//===- KanagawaDialect.cpp - Implementation of Kanagawa dialect -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,37 +6,37 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "mlir/IR/DialectImplementation.h"
#include "llvm/ADT/TypeSwitch.h"
using namespace circt;
using namespace ibis;
using namespace kanagawa;
// Pull in the dialect definition.
#include "circt/Dialect/Ibis/IbisDialect.cpp.inc"
#include "circt/Dialect/Kanagawa/KanagawaDialect.cpp.inc"
void IbisDialect::initialize() {
void KanagawaDialect::initialize() {
registerTypes();
registerAttributes();
// Register operations.
addOperations<
#define GET_OP_LIST
#include "circt/Dialect/Ibis/Ibis.cpp.inc"
#include "circt/Dialect/Kanagawa/Kanagawa.cpp.inc"
>();
}
void IbisDialect::registerAttributes() {
void KanagawaDialect::registerAttributes() {
addAttributes<
#define GET_ATTRDEF_LIST
#include "circt/Dialect/Ibis/IbisAttributes.cpp.inc"
#include "circt/Dialect/Kanagawa/KanagawaAttributes.cpp.inc"
>();
}
// Provide implementations for the enums we use.
#include "circt/Dialect/Ibis/IbisEnums.cpp.inc"
#include "circt/Dialect/Kanagawa/KanagawaEnums.cpp.inc"
#define GET_ATTRDEF_CLASSES
#include "circt/Dialect/Ibis/IbisAttributes.cpp.inc"
#include "circt/Dialect/Kanagawa/KanagawaAttributes.cpp.inc"

View File

@ -1,4 +1,4 @@
//===- IbisOps.cpp - Implementation of Ibis dialect ops -------------------===//
//===- KanagawaOps.cpp - Implementation of Kanagawa dialect ops -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/DC/DCTypes.h"
#include "circt/Support/ParsingUtils.h"
@ -19,7 +19,7 @@
using namespace mlir;
using namespace circt;
using namespace ibis;
using namespace kanagawa;
template <typename TSymAttr>
ParseResult parseScopeRefFromName(OpAsmParser &parser, Type &scopeRefType,
@ -36,7 +36,7 @@ void printScopeRefFromName(OpAsmPrinter &p, Operation *op, Type type,
// symbol.
}
// Generates a name for Ibis values.
// Generates a name for Kanagawa values.
// NOLINTBEGIN(misc-no-recursion)
static llvm::raw_string_ostream &genValueName(llvm::raw_string_ostream &os,
Value value) {
@ -72,7 +72,7 @@ static llvm::raw_string_ostream &genValueName(llvm::raw_string_ostream &os,
}
// NOLINTEND(misc-no-recursion)
// Generates a name for Ibis values, and returns a StringAttr.
// Generates a name for Kanagawa values, and returns a StringAttr.
static StringAttr genValueNameAttr(Value v) {
std::string s;
llvm::raw_string_ostream os(s);
@ -85,19 +85,19 @@ static StringAttr genValueNameAttr(Value v) {
//===----------------------------------------------------------------------===//
FailureOr<mlir::TypedValue<ScopeRefType>>
circt::ibis::detail::getThisFromScope(Operation *op) {
circt::kanagawa::detail::getThisFromScope(Operation *op) {
auto scopeOp = cast<ScopeOpInterface>(op);
auto thisOps = scopeOp.getBodyBlock()->getOps<ibis::ThisOp>();
auto thisOps = scopeOp.getBodyBlock()->getOps<kanagawa::ThisOp>();
if (thisOps.empty())
return op->emitOpError("must contain a 'ibis.this' operation");
return op->emitOpError("must contain a 'kanagawa.this' operation");
if (std::next(thisOps.begin()) != thisOps.end())
return op->emitOpError("must contain only one 'ibis.this' operation");
return op->emitOpError("must contain only one 'kanagawa.this' operation");
return (*thisOps.begin()).getThisRef();
}
LogicalResult circt::ibis::detail::verifyScopeOpInterface(Operation *op) {
LogicalResult circt::kanagawa::detail::verifyScopeOpInterface(Operation *op) {
if (failed(getThisFromScope(op)))
return failure();
@ -325,7 +325,7 @@ PortOpInterface GetPortOp::getPort(const hw::InnerRefNamespace &ns) {
LogicalResult GetPortOp::canonicalize(GetPortOp op, PatternRewriter &rewriter) {
// Canonicalize away get_port on %this in favor of using the port SSA value
// directly.
// get_port(%this, @P) -> ibis.port.#
// get_port(%this, @P) -> kanagawa.port.#
auto parentScope = dyn_cast<ScopeOpInterface>(op->getParentOp());
if (parentScope) {
auto scopeThis = parentScope.getThis();
@ -425,15 +425,17 @@ LogicalResult PathStepAttr::verify(function_ref<InFlightDiagnostic()> emitError,
mlir::FlatSymbolRefAttr instance) {
// 'parent' should never have an instance name specified.
if (direction == PathDirection::Parent && instance)
return emitError() << "ibis.step 'parent' may not specify an instance name";
return emitError()
<< "kanagawa.step 'parent' may not specify an instance name";
if (direction == PathDirection::Child && !instance)
return emitError() << "ibis.step 'child' must specify an instance name";
return emitError() << "kanagawa.step 'child' must specify an instance name";
// Only allow scoperefs
auto scoperefType = llvm::dyn_cast<ScopeRefType>(type);
if (!scoperefType)
return emitError() << "ibis.step type must be an !ibis.scoperef type";
return emitError()
<< "kanagawa.step type must be an !kanagawa.scoperef type";
return success();
}
@ -441,7 +443,7 @@ LogicalResult PathStepAttr::verify(function_ref<InFlightDiagnostic()> emitError,
LogicalResult PathOp::verifyInnerRefs(hw::InnerRefNamespace &ns) {
auto pathRange = getPathAsRange();
if (pathRange.empty())
return emitOpError() << "ibis.path must have at least one step";
return emitOpError() << "kanagawa.path must have at least one step";
// Verify that each referenced child symbol actually exists at the module
// level.
@ -453,7 +455,7 @@ LogicalResult PathOp::verifyInnerRefs(hw::InnerRefNamespace &ns) {
auto *targetScope = ns.lookupOp(scopeRefSym);
if (!targetScope)
return emitOpError() << "ibis.step scoperef symbol '@"
return emitOpError() << "kanagawa.step scoperef symbol '@"
<< scopeRefSym.getName().getValue()
<< "' does not exist";
}
@ -462,15 +464,15 @@ LogicalResult PathOp::verifyInnerRefs(hw::InnerRefNamespace &ns) {
PathStepAttr lastStep = *std::prev(getPathAsRange().end());
ScopeRefType lastStepType = cast<ScopeRefType>(lastStep.getType());
if (!lastStepType.getScopeRef())
return emitOpError()
<< "last ibis.step in path must specify a symbol for the scoperef";
return emitOpError() << "last kanagawa.step in path must specify a symbol "
"for the scoperef";
return success();
}
LogicalResult PathOp::canonicalize(PathOp op, PatternRewriter &rewriter) {
// Canonicalize away ibis.path [ibis.child] to just referencing the instance
// in the current scope.
// Canonicalize away kanagawa.path [kanagawa.child] to just referencing the
// instance in the current scope.
auto range = op.getPathAsRange();
size_t pathSize = std::distance(range.begin(), range.end());
PathStepAttr firstStep = *range.begin();
@ -817,8 +819,8 @@ InlineStaticBlockEndOp InlineStaticBlockBeginOp::getEndOp() {
// TableGen generated logic
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisInterfaces.cpp.inc"
#include "circt/Dialect/Kanagawa/KanagawaInterfaces.cpp.inc"
// Provide the autogenerated implementation guts for the Op classes.
#define GET_OP_CLASSES
#include "circt/Dialect/Ibis/Ibis.cpp.inc"
#include "circt/Dialect/Kanagawa/Kanagawa.cpp.inc"

View File

@ -1,4 +1,4 @@
//===- IbisTypes.cpp - Implementation of Ibis dialect types ---------------===//
//===- KanagawaTypes.cpp - Implementation of Kanagawa dialect types -------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,18 +6,18 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "mlir/IR/DialectImplementation.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/TypeSwitch.h"
using namespace circt;
using namespace ibis;
using namespace kanagawa;
bool circt::ibis::isOpaqueScopeRefType(mlir::Type type) {
bool circt::kanagawa::isOpaqueScopeRefType(mlir::Type type) {
auto scopeRef = dyn_cast<ScopeRefType>(type);
if (!scopeRef)
return false;
@ -47,12 +47,12 @@ void ScopeRefType::print(AsmPrinter &p) const {
}
#define GET_TYPEDEF_CLASSES
#include "circt/Dialect/Ibis/IbisTypes.cpp.inc"
#include "circt/Dialect/Kanagawa/KanagawaTypes.cpp.inc"
void IbisDialect::registerTypes() {
void KanagawaDialect::registerTypes() {
// Register types.
addTypes<
#define GET_TYPEDEF_LIST
#include "circt/Dialect/Ibis/IbisTypes.cpp.inc"
#include "circt/Dialect/Kanagawa/KanagawaTypes.cpp.inc"
>();
}

View File

@ -0,0 +1,36 @@
add_circt_dialect_library(CIRCTKanagawaTransforms
KanagawaCallPrep.cpp
KanagawaContainerize.cpp
KanagawaTunneling.cpp
KanagawaPortrefLowering.cpp
KanagawaCleanSelfdrivers.cpp
KanagawaContainersToHW.cpp
KanagawaArgifyBlocksPass.cpp
KanagawaReblockPass.cpp
KanagawaInlineSBlocksPass.cpp
KanagawaConvertCFToHandshake.cpp
KanagawaPassPipelines.cpp
KanagawaPrepareScheduling.cpp
KanagawaConvertHandshakeToDC.cpp
KanagawaMethodsToContainers.cpp
KanagawaAddOperatorLibrary.cpp
DEPENDS
CIRCTKanagawaTransformsIncGen
LINK_LIBS PUBLIC
CIRCTDC
CIRCTHandshake
CIRCTPipelineOps
CIRCTCFToHandshake
CIRCTHandshakeToDC
CIRCTKanagawa
CIRCTSSP
CIRCTHW
CIRCTHWTransforms
CIRCTSupport
CIRCTTransforms
MLIRIR
MLIRPass
MLIRTransformUtils
)

View File

@ -1,4 +1,4 @@
//===- IbisAddOperatorLibraryPass.cpp -------------------------------------===//
//===- KanagawaAddOperatorLibraryPass.cpp ---------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,15 +6,15 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "mlir/Pass/Pass.h"
#include "circt/Dialect/Comb/CombOps.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "circt/Dialect/SSP/SSPOps.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
@ -25,20 +25,20 @@
#include <iterator>
namespace circt {
namespace ibis {
#define GEN_PASS_DEF_IBISADDOPERATORLIBRARY
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
} // namespace ibis
namespace kanagawa {
#define GEN_PASS_DEF_KANAGAWAADDOPERATORLIBRARY
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace kanagawa
} // namespace circt
using namespace mlir;
using namespace circt;
using namespace ibis;
using namespace kanagawa;
namespace {
struct AddOperatorLibraryPass
: public circt::ibis::impl::IbisAddOperatorLibraryBase<
: public circt::kanagawa::impl::KanagawaAddOperatorLibraryBase<
AddOperatorLibraryPass> {
void runOnOperation() override;
};
@ -58,7 +58,7 @@ void AddOperatorLibraryPass::runOnOperation() {
auto b = ImplicitLocOpBuilder::atBlockBegin(getOperation().getLoc(),
getOperation().getBody());
auto opLib = b.create<ssp::OperatorLibraryOp>();
opLib.setSymNameAttr(b.getStringAttr(kIbisOperatorLibName));
opLib.setSymNameAttr(b.getStringAttr(kKanagawaOperatorLibName));
b.setInsertionPointToStart(opLib.getBodyBlock());
// Provide definitions for some comb ops - just latency properties for now.
@ -84,6 +84,6 @@ void AddOperatorLibraryPass::runOnOperation() {
addOperator<comb::ShrSOp>(b, 1);
}
std::unique_ptr<Pass> circt::ibis::createAddOperatorLibraryPass() {
std::unique_ptr<Pass> circt::kanagawa::createAddOperatorLibraryPass() {
return std::make_unique<AddOperatorLibraryPass>();
}

View File

@ -1,4 +1,4 @@
//===- IbisArgifyBlocksPass.cpp -------------------------------------------===//
//===- KanagawaArgifyBlocksPass.cpp ---------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,26 +6,26 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "mlir/Pass/Pass.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "mlir/Transforms/DialectConversion.h"
namespace circt {
namespace ibis {
#define GEN_PASS_DEF_IBISARGIFYBLOCKS
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
} // namespace ibis
namespace kanagawa {
#define GEN_PASS_DEF_KANAGAWAARGIFYBLOCKS
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace kanagawa
} // namespace circt
using namespace circt;
using namespace ibis;
using namespace kanagawa;
namespace {
@ -84,7 +84,7 @@ struct BlockConversionPattern : public OpConversionPattern<StaticBlockOp> {
};
struct ArgifyBlocksPass
: public circt::ibis::impl::IbisArgifyBlocksBase<ArgifyBlocksPass> {
: public circt::kanagawa::impl::KanagawaArgifyBlocksBase<ArgifyBlocksPass> {
void runOnOperation() override;
};
} // anonymous namespace
@ -93,7 +93,7 @@ void ArgifyBlocksPass::runOnOperation() {
auto *ctx = &getContext();
ConversionTarget target(*ctx);
target.addIllegalOp<StaticBlockOp>();
target.addLegalDialect<IbisDialect>();
target.addLegalDialect<KanagawaDialect>();
RewritePatternSet patterns(ctx);
patterns.add<BlockConversionPattern>(ctx);
@ -103,6 +103,6 @@ void ArgifyBlocksPass::runOnOperation() {
signalPassFailure();
}
std::unique_ptr<Pass> circt::ibis::createArgifyBlocksPass() {
std::unique_ptr<Pass> circt::kanagawa::createArgifyBlocksPass() {
return std::make_unique<ArgifyBlocksPass>();
}

View File

@ -1,4 +1,4 @@
//===- IbisCallPrep.cpp - Implementation of call prep lowering ------------===//
//===- KanagawaCallPrep.cpp - Implementation of call prep lowering --------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,14 +6,14 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "mlir/Pass/Pass.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "circt/Dialect/HW/ConversionPatterns.h"
#include "circt/Dialect/HW/HWOps.h"
@ -23,14 +23,14 @@
#include "mlir/Transforms/DialectConversion.h"
namespace circt {
namespace ibis {
#define GEN_PASS_DEF_IBISCALLPREP
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
} // namespace ibis
namespace kanagawa {
#define GEN_PASS_DEF_KANAGAWACALLPREP
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace kanagawa
} // namespace circt
using namespace circt;
using namespace ibis;
using namespace kanagawa;
/// Build indexes to make lookups faster. Create the new argument types as well.
struct CallPrepPrecomputed {
@ -131,7 +131,7 @@ void MergeCallArgs::rewrite(CallOp call, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const {
auto loc = call.getLoc();
rewriter.setInsertionPoint(call);
auto method = call->getParentOfType<ibis::MethodLikeOpInterface>();
auto method = call->getParentOfType<kanagawa::MethodLikeOpInterface>();
// Use the 'info' accelerator structures to find the argument type.
auto argStructEntry = info.argTypes.find(call.getCalleeAttr());
@ -208,7 +208,8 @@ void MergeMethodArgs::rewrite(MethodOp func, OpAdaptor adaptor,
namespace {
/// Run all the physical lowerings.
struct CallPrepPass : public circt::ibis::impl::IbisCallPrepBase<CallPrepPass> {
struct CallPrepPass
: public circt::kanagawa::impl::KanagawaCallPrepBase<CallPrepPass> {
void runOnOperation() override;
private:
@ -249,6 +250,6 @@ LogicalResult CallPrepPass::merge(const CallPrepPrecomputed &info) {
return applyPartialConversion(getOperation(), target, std::move(patterns));
}
std::unique_ptr<Pass> circt::ibis::createCallPrepPass() {
std::unique_ptr<Pass> circt::kanagawa::createCallPrepPass() {
return std::make_unique<CallPrepPass>();
}

View File

@ -1,4 +1,4 @@
//===- IbisCleanSelfdrivers.cpp -------------------------------------------===//
//===- KanagawaCleanSelfdrivers.cpp ---------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,32 +6,32 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "mlir/Pass/Pass.h"
#include "circt/Dialect/HW/HWOps.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "circt/Support/InstanceGraph.h"
#include "llvm/Support/Debug.h"
#include "mlir/Transforms/DialectConversion.h"
#include "llvm/ADT/TypeSwitch.h"
#define DEBUG_TYPE "ibis-clean-selfdrivers"
#define DEBUG_TYPE "kanagawa-clean-selfdrivers"
namespace circt {
namespace ibis {
#define GEN_PASS_DEF_IBISCLEANSELFDRIVERS
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
} // namespace ibis
namespace kanagawa {
#define GEN_PASS_DEF_KANAGAWACLEANSELFDRIVERS
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace kanagawa
} // namespace circt
using namespace circt;
using namespace ibis;
using namespace kanagawa;
using namespace circt::igraph;
// Returns true if the given input port is self-driven, i.e. there exists
@ -156,10 +156,10 @@ struct InputPortOpConversionPattern : public OpConversionPattern<InputPortOp> {
for (auto reader : readers)
rewriter.replaceOp(reader, wire);
// Since Ibis allows for input ports to be read from outside the container,
// we need to check the instance graph to see whether this is the case.
// If so, we need to add an output port to the container and connect it to
// the assigned value.
// Since Kanagawa allows for input ports to be read from outside the
// container, we need to check the instance graph to see whether this is the
// case. If so, we need to add an output port to the container and connect
// it to the assigned value.
auto parentModuleOp = dyn_cast<ModuleOpInterface>(op->getParentOp());
if (parentModuleOp) {
InstanceGraphNode *node = ig.lookup(parentModuleOp);
@ -191,7 +191,8 @@ protected:
};
struct CleanSelfdriversPass
: public circt::ibis::impl::IbisCleanSelfdriversBase<CleanSelfdriversPass> {
: public circt::kanagawa::impl::KanagawaCleanSelfdriversBase<
CleanSelfdriversPass> {
void runOnOperation() override;
LogicalResult cleanInstanceSide();
@ -210,7 +211,7 @@ LogicalResult CleanSelfdriversPass::cleanInstanceSide() {
LogicalResult CleanSelfdriversPass::cleanContainerSide() {
auto *ctx = &getContext();
ConversionTarget target(*ctx);
target.addLegalDialect<IbisDialect>();
target.addLegalDialect<KanagawaDialect>();
target.addLegalOp<hw::WireOp>();
target.addDynamicallyLegalOp<InputPortOp>(
[](InputPortOp op) { return !isSelfDriven(op); });
@ -231,6 +232,6 @@ void CleanSelfdriversPass::runOnOperation() {
return signalPassFailure();
}
std::unique_ptr<Pass> circt::ibis::createCleanSelfdriversPass() {
std::unique_ptr<Pass> circt::kanagawa::createCleanSelfdriversPass() {
return std::make_unique<CleanSelfdriversPass>();
}

View File

@ -1,4 +1,4 @@
//===- IbisContainerize.cpp - Implementation of containerizing ------------===//
//===- KanagawaContainerize.cpp - Implementation of containerizing --------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,28 +6,28 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "mlir/Pass/Pass.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "circt/Support/Namespace.h"
#include "circt/Support/SymCache.h"
#include "mlir/Transforms/DialectConversion.h"
namespace circt {
namespace ibis {
#define GEN_PASS_DEF_IBISCONTAINERIZE
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
} // namespace ibis
namespace kanagawa {
#define GEN_PASS_DEF_KANAGAWACONTAINERIZE
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace kanagawa
} // namespace circt
using namespace circt;
using namespace ibis;
using namespace kanagawa;
namespace {
@ -58,7 +58,7 @@ struct OutlineContainerPattern : public OpConversionPattern<ContainerOp> {
rewriter.mergeBlocks(op.getBodyBlock(), newContainer.getBodyBlock(), {});
// Rename the ibis.this operation to refer to the proper op.
// Rename the kanagawa.this operation to refer to the proper op.
auto thisOp =
cast<ThisOp>(cast<ScopeOpInterface>(*newContainer.getOperation())
.getThis()
@ -111,7 +111,7 @@ struct InstanceToContainerInstancePattern
/// Run all the physical lowerings.
struct ContainerizePass
: public circt::ibis::impl::IbisContainerizeBase<ContainerizePass> {
: public circt::kanagawa::impl::KanagawaContainerizeBase<ContainerizePass> {
void runOnOperation() override;
private:
@ -126,9 +126,9 @@ private:
LogicalResult ContainerizePass::outlineContainers() {
auto *context = &getContext();
ConversionTarget target(*context);
target.addLegalDialect<IbisDialect>();
target.addLegalDialect<KanagawaDialect>();
target.addDynamicallyLegalOp<ContainerOp>(
[&](auto *op) { return !isa<ibis::ClassOp>(op->getParentOp()); });
[&](auto *op) { return !isa<kanagawa::ClassOp>(op->getParentOp()); });
RewritePatternSet patterns(context);
// Setup a namespace to ensure that the new container names are unique.
@ -150,7 +150,7 @@ LogicalResult ContainerizePass::outlineContainers() {
LogicalResult ContainerizePass::containerizeClasses() {
auto *context = &getContext();
ConversionTarget target(*context);
target.addLegalDialect<IbisDialect>();
target.addLegalDialect<KanagawaDialect>();
target.addIllegalOp<ClassOp, InstanceOp>();
RewritePatternSet patterns(context);
patterns.insert<ClassToContainerPattern, InstanceToContainerInstancePattern>(
@ -163,6 +163,6 @@ void ContainerizePass::runOnOperation() {
signalPassFailure();
}
std::unique_ptr<Pass> circt::ibis::createContainerizePass() {
std::unique_ptr<Pass> circt::kanagawa::createContainerizePass() {
return std::make_unique<ContainerizePass>();
}

View File

@ -1,4 +1,4 @@
//===- IbisContainersToHW.cpp ---------------------------------------------===//
//===- KanagawaContainersToHW.cpp -----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,15 +6,15 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "mlir/Pass/Pass.h"
#include "circt/Dialect/HW/HWOps.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "circt/Support/Namespace.h"
#include "mlir/IR/OperationSupport.h"
@ -22,14 +22,14 @@
#include "llvm/ADT/TypeSwitch.h"
namespace circt {
namespace ibis {
#define GEN_PASS_DEF_IBISCONTAINERSTOHW
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
} // namespace ibis
namespace kanagawa {
#define GEN_PASS_DEF_KANAGAWACONTAINERSTOHW
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace kanagawa
} // namespace circt
using namespace circt;
using namespace ibis;
using namespace kanagawa;
namespace {
@ -152,7 +152,7 @@ struct ContainerOpConversionPattern : public OpConversionPattern<ContainerOp> {
auto reader = dyn_cast<PortReadOp>(user);
if (!reader)
return rewriter.notifyMatchFailure(
user, "expected only ibis.port.read ops of the input port");
user, "expected only kanagawa.port.read ops of the input port");
rewriter.replaceOp(reader, barg);
}
@ -160,7 +160,7 @@ struct ContainerOpConversionPattern : public OpConversionPattern<ContainerOp> {
rewriter.eraseOp(inputPort);
}
// Adjust the hw.output op to use ibis.port.write values
// Adjust the hw.output op to use kanagawa.port.write values
llvm::SmallVector<Value> outputValues;
for (auto [idx, output] : llvm::enumerate(cpi.hwPorts->getOutputs())) {
auto outputPort = cpi.opOutputs.at(output.name);
@ -169,7 +169,7 @@ struct ContainerOpConversionPattern : public OpConversionPattern<ContainerOp> {
size_t nUsers = std::distance(users.begin(), users.end());
if (nUsers != 1)
return outputPort->emitOpError()
<< "expected exactly one ibis.port.write op of the output "
<< "expected exactly one kanagawa.port.write op of the output "
"port: "
<< output.name.str() << " found: " << nUsers;
auto writer = cast<PortWriteOp>(*users.begin());
@ -232,7 +232,7 @@ struct ContainerInstanceOpConversionPattern
auto getPort = dyn_cast<GetPortOp>(user);
if (!getPort)
return rewriter.notifyMatchFailure(
user, "expected only ibis.get_port op usage of the instance");
user, "expected only kanagawa.get_port op usage of the instance");
for (auto *user : getPort->getUsers()) {
auto res =
@ -244,7 +244,7 @@ struct ContainerInstanceOpConversionPattern
read});
if (!inserted)
return rewriter.notifyMatchFailure(
read, "expected only one ibis.port.read op of the "
read, "expected only one kanagawa.port.read op of the "
"output port");
return success();
})
@ -256,13 +256,14 @@ struct ContainerInstanceOpConversionPattern
if (!inserted)
return rewriter.notifyMatchFailure(
write,
"expected only one ibis.port.write op of the input "
"expected only one kanagawa.port.write op of the input "
"port");
return success();
})
.Default([&](auto op) {
return rewriter.notifyMatchFailure(
op, "expected only ibis.port.read or ibis.port.write ops "
op, "expected only kanagawa.port.read or "
"kanagawa.port.write ops "
"of the "
"instance");
});
@ -281,7 +282,8 @@ struct ContainerInstanceOpConversionPattern
ers << "Error when lowering instance ";
op.print(ers, mlir::OpPrintingFlags().printGenericOpForm());
ers << "\nexpected exactly one ibis.port.write op of each input port. "
ers << "\nexpected exactly one kanagawa.port.write op of each input "
"port. "
"Mising port assignments were:\n";
for (auto input : cpi.hwPorts->getInputs()) {
if (inputWritesToUse.find(input.name) == inputWritesToUse.end())
@ -345,7 +347,8 @@ struct ContainerInstanceOpConversionPattern
}; // namespace
struct ContainersToHWPass
: public circt::ibis::impl::IbisContainersToHWBase<ContainersToHWPass> {
: public circt::kanagawa::impl::KanagawaContainersToHWBase<
ContainersToHWPass> {
void runOnOperation() override;
};
} // anonymous namespace
@ -369,18 +372,19 @@ void ContainersToHWPass::runOnOperation() {
target.addIllegalOp<ContainerOp, ContainerInstanceOp, ThisOp>();
target.markUnknownOpDynamicallyLegal([](Operation *) { return true; });
// Remove the name of the ibis.design's from the namespace - The ibis.design
// op will be removed after this pass, and there may be ibis.component's
// inside the design that have the same name as the design; we want that
// name to persist, and not be falsely considered a duplicate.
// Remove the name of the kanagawa.design's from the namespace - The
// kanagawa.design op will be removed after this pass, and there may be
// kanagawa.component's inside the design that have the same name as the
// design; we want that name to persist, and not be falsely considered a
// duplicate.
for (auto designOp : getOperation().getOps<DesignOp>())
modNamespace.erase(designOp.getSymName());
// Parts of the conversion patterns will update operations in place, which in
// turn requires the updated operations to be legalizeable. These in-place ops
// also include ibis ops that eventually will get replaced once all of the
// also include kanagawa ops that eventually will get replaced once all of the
// patterns apply.
target.addLegalDialect<IbisDialect>();
target.addLegalDialect<KanagawaDialect>();
RewritePatternSet patterns(ctx);
patterns.add<ContainerOpConversionPattern>(ctx, modNamespace, portOrder,
@ -399,6 +403,6 @@ void ContainersToHWPass::runOnOperation() {
design.erase();
}
std::unique_ptr<Pass> circt::ibis::createContainersToHWPass() {
std::unique_ptr<Pass> circt::kanagawa::createContainersToHWPass() {
return std::make_unique<ContainersToHWPass>();
}

View File

@ -1,4 +1,4 @@
//===- IbisConvertCFToHandshakePass.cpp -----------------------------------===//
//===- KanagawaConvertCFToHandshakePass.cpp -------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,14 +6,14 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "mlir/Pass/Pass.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "circt/Transforms/Passes.h"
#include "mlir/Transforms/DialectConversion.h"
@ -21,20 +21,20 @@
#include "circt/Conversion/CFToHandshake.h"
namespace circt {
namespace ibis {
#define GEN_PASS_DEF_IBISCONVERTCFTOHANDSHAKE
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
} // namespace ibis
namespace kanagawa {
#define GEN_PASS_DEF_KANAGAWACONVERTCFTOHANDSHAKE
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace kanagawa
} // namespace circt
using namespace mlir;
using namespace circt;
using namespace ibis;
using namespace kanagawa;
namespace {
struct ConvertCFToHandshakePass
: public circt::ibis::impl::IbisConvertCFToHandshakeBase<
: public circt::kanagawa::impl::KanagawaConvertCFToHandshakeBase<
ConvertCFToHandshakePass> {
void runOnOperation() override;
@ -63,7 +63,7 @@ LogicalResult ConvertCFToHandshakePass::convertMethod(MethodOp method) {
method.erase();
handshake::HandshakeLowering fol(dataflowMethodOp.getBody());
if (failed(handshake::lowerRegion<ibis::ReturnOp, ibis::ReturnOp>(
if (failed(handshake::lowerRegion<kanagawa::ReturnOp, kanagawa::ReturnOp>(
fol,
/*sourceConstants*/ false, /*disableTaskPipelining*/ false,
entryCtrl)))
@ -80,6 +80,6 @@ void ConvertCFToHandshakePass::runOnOperation() {
}
}
std::unique_ptr<Pass> circt::ibis::createConvertCFToHandshakePass() {
std::unique_ptr<Pass> circt::kanagawa::createConvertCFToHandshakePass() {
return std::make_unique<ConvertCFToHandshakePass>();
}

View File

@ -1,4 +1,4 @@
//===- IbisConvertHandshakeToDCPass.cpp -----------------------------------===//
//===- KanagawaConvertHandshakeToDCPass.cpp -------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,16 +6,16 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "mlir/Pass/Pass.h"
#include "circt/Dialect/DC/DCTypes.h"
#include "circt/Dialect/HW/ConversionPatterns.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "circt/Transforms/Passes.h"
#include "mlir/Transforms/DialectConversion.h"
@ -23,20 +23,20 @@
#include "circt/Conversion/HandshakeToDC.h"
namespace circt {
namespace ibis {
#define GEN_PASS_DEF_IBISCONVERTHANDSHAKETODC
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
} // namespace ibis
namespace kanagawa {
#define GEN_PASS_DEF_KANAGAWACONVERTHANDSHAKETODC
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace kanagawa
} // namespace circt
using namespace mlir;
using namespace circt;
using namespace ibis;
using namespace kanagawa;
namespace {
struct ConvertHandshakeToDCPass
: public circt::ibis::impl::IbisConvertHandshakeToDCBase<
: public circt::kanagawa::impl::KanagawaConvertHandshakeToDCBase<
ConvertHandshakeToDCPass> {
void runOnOperation() override;
};
@ -48,7 +48,7 @@ class ReturnOpConversion : public OpConversionPattern<ReturnOp> {
LogicalResult
matchAndRewrite(ReturnOp op, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override {
rewriter.replaceOpWithNewOp<ibis::ReturnOp>(op, adaptor.getOperands());
rewriter.replaceOpWithNewOp<kanagawa::ReturnOp>(op, adaptor.getOperands());
return success();
}
};
@ -86,22 +86,22 @@ static bool isDCTypedOp(Operation *op) {
}
void ConvertHandshakeToDCPass::runOnOperation() {
ibis::ClassOp classOp = getOperation();
kanagawa::ClassOp classOp = getOperation();
auto targetModifier = [&](mlir::ConversionTarget &target) {
target.addDynamicallyLegalOp<ibis::DataflowMethodOp>(
[](ibis::DataflowMethodOp op) {
target.addDynamicallyLegalOp<kanagawa::DataflowMethodOp>(
[](kanagawa::DataflowMethodOp op) {
auto methodLikeOp = cast<MethodLikeOpInterface>(op.getOperation());
return llvm::all_of(methodLikeOp.getArgumentTypes(), isDCType) &&
llvm::all_of(methodLikeOp.getResultTypes(), isDCType);
});
target.addDynamicallyLegalOp<ibis::ReturnOp>(isDCTypedOp);
target.addLegalDialect<hw::HWDialect, ibis::IbisDialect>();
target.addIllegalOp<ibis::IsolatedStaticBlockOp>();
target.addDynamicallyLegalOp<kanagawa::ReturnOp>(isDCTypedOp);
target.addLegalDialect<hw::HWDialect, kanagawa::KanagawaDialect>();
target.addIllegalOp<kanagawa::IsolatedStaticBlockOp>();
// ibis.sblock.dc ops are recursively legal - we're only considering the
// kanagawa.sblock.dc ops are recursively legal - we're only considering the
// DataflowMethodOp's region for conversion.
target.addLegalOp<ibis::DCBlockOp>();
target.markOpRecursivelyLegal<ibis::DCBlockOp>();
target.addLegalOp<kanagawa::DCBlockOp>();
target.markOpRecursivelyLegal<kanagawa::DCBlockOp>();
};
auto patternBuilder = [&](TypeConverter &typeConverter,
@ -120,6 +120,6 @@ void ConvertHandshakeToDCPass::runOnOperation() {
signalPassFailure();
}
std::unique_ptr<Pass> circt::ibis::createConvertHandshakeToDCPass() {
std::unique_ptr<Pass> circt::kanagawa::createConvertHandshakeToDCPass() {
return std::make_unique<ConvertHandshakeToDCPass>();
}

View File

@ -1,4 +1,4 @@
//===- IbisInlineSBlocksPass.cpp ------------------------------------------===//
//===- KanagawaInlineSBlocksPass.cpp --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,14 +6,14 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "mlir/Pass/Pass.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
@ -24,31 +24,33 @@
#include <iterator>
namespace circt {
namespace ibis {
#define GEN_PASS_DEF_IBISINLINESBLOCKS
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
} // namespace ibis
namespace kanagawa {
#define GEN_PASS_DEF_KANAGAWAINLINESBLOCKS
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace kanagawa
} // namespace circt
using namespace mlir;
using namespace circt;
using namespace ibis;
using namespace kanagawa;
namespace {
struct InlineSBlocksPass
: public circt::ibis::impl::IbisInlineSBlocksBase<InlineSBlocksPass> {
: public circt::kanagawa::impl::KanagawaInlineSBlocksBase<
InlineSBlocksPass> {
void runOnOperation() override;
};
class InlineSBlocksPattern : public OpConversionPattern<ibis::StaticBlockOp> {
class InlineSBlocksPattern
: public OpConversionPattern<kanagawa::StaticBlockOp> {
public:
using OpConversionPattern<ibis::StaticBlockOp>::OpConversionPattern;
using OpConversionPattern<kanagawa::StaticBlockOp>::OpConversionPattern;
using OpAdaptor =
typename OpConversionPattern<ibis::StaticBlockOp>::OpAdaptor;
typename OpConversionPattern<kanagawa::StaticBlockOp>::OpAdaptor;
LogicalResult
matchAndRewrite(ibis::StaticBlockOp op, OpAdaptor adaptor,
matchAndRewrite(kanagawa::StaticBlockOp op, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override {
Location loc = op.getLoc();
@ -57,7 +59,8 @@ public:
if (hasAttributes) {
// Start the inline block...
auto inlineStart = rewriter.create<ibis::InlineStaticBlockBeginOp>(loc);
auto inlineStart =
rewriter.create<kanagawa::InlineStaticBlockBeginOp>(loc);
inlineStart->setAttrs(op->getAttrs());
}
@ -66,15 +69,15 @@ public:
BlockReturnOp ret = cast<BlockReturnOp>(sblockBody->getTerminator());
rewriter.inlineBlockBefore(sblockBody, op->getNextNode());
// Replace the ibis.sblock return values with the values that were defined
// (returned from) within the sblock body, and erase the return op.
// Replace the kanagawa.sblock return values with the values that were
// defined (returned from) within the sblock body, and erase the return op.
for (auto [res, val] : llvm::zip(op.getResults(), ret.getRetValues()))
rewriter.replaceAllUsesWith(res, val);
if (hasAttributes) {
// Close the inline block
rewriter.setInsertionPoint(ret);
rewriter.create<ibis::InlineStaticBlockEndOp>(loc);
rewriter.create<kanagawa::InlineStaticBlockEndOp>(loc);
}
rewriter.eraseOp(ret);
@ -88,9 +91,9 @@ public:
void InlineSBlocksPass::runOnOperation() {
MethodOp parent = getOperation();
ConversionTarget target(getContext());
target.addIllegalOp<ibis::StaticBlockOp>();
// Mark everything but `ibis.sblock` as legal - we need a legalization pattern
// for any possible op that gets inlined from a block.
target.addIllegalOp<kanagawa::StaticBlockOp>();
// Mark everything but `kanagawa.sblock` as legal - we need a legalization
// pattern for any possible op that gets inlined from a block.
target.markUnknownOpDynamicallyLegal([](Operation *op) { return true; });
RewritePatternSet patterns(&getContext());
patterns.add<InlineSBlocksPattern>(&getContext());
@ -99,6 +102,6 @@ void InlineSBlocksPass::runOnOperation() {
return signalPassFailure();
}
std::unique_ptr<Pass> circt::ibis::createInlineSBlocksPass() {
std::unique_ptr<Pass> circt::kanagawa::createInlineSBlocksPass() {
return std::make_unique<InlineSBlocksPass>();
}

View File

@ -1,4 +1,4 @@
//===- IbisMethodsToContainers.cpp - Implementation of containerizing -----===//
//===- KanagawaMethodsToContainers.cpp - Implementation of containerizing -===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,28 +6,28 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "mlir/Pass/Pass.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "circt/Support/Namespace.h"
#include "circt/Support/SymCache.h"
#include "mlir/Transforms/DialectConversion.h"
namespace circt {
namespace ibis {
#define GEN_PASS_DEF_IBISCONVERTMETHODSTOCONTAINERS
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
} // namespace ibis
namespace kanagawa {
#define GEN_PASS_DEF_KANAGAWACONVERTMETHODSTOCONTAINERS
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace kanagawa
} // namespace circt
using namespace circt;
using namespace ibis;
using namespace kanagawa;
namespace {
@ -76,7 +76,7 @@ struct DataflowMethodOpConversion
};
struct MethodsToContainersPass
: public circt::ibis::impl::IbisConvertMethodsToContainersBase<
: public circt::kanagawa::impl::KanagawaConvertMethodsToContainersBase<
MethodsToContainersPass> {
void runOnOperation() override;
};
@ -85,7 +85,7 @@ struct MethodsToContainersPass
void MethodsToContainersPass::runOnOperation() {
auto *context = &getContext();
ConversionTarget target(*context);
target.addLegalDialect<IbisDialect>();
target.addLegalDialect<KanagawaDialect>();
target.addIllegalOp<DataflowMethodOp>();
target.addIllegalOp<ReturnOp>();
RewritePatternSet patterns(context);
@ -96,6 +96,6 @@ void MethodsToContainersPass::runOnOperation() {
signalPassFailure();
}
std::unique_ptr<Pass> circt::ibis::createConvertMethodsToContainersPass() {
std::unique_ptr<Pass> circt::kanagawa::createConvertMethodsToContainersPass() {
return std::make_unique<MethodsToContainersPass>();
}

View File

@ -1,4 +1,4 @@
//===- IbisPassPipelines.cpp - Ibis pass pipelines ------------------------===//
//===- KanagawaPassPipelines.cpp - Kanagawa pass pipelines ----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,16 +6,16 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisPassPipelines.h"
#include "circt/Dialect/Kanagawa/KanagawaPassPipelines.h"
#include "circt/Dialect/HW/HWPasses.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Transforms/Passes.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "mlir/Transforms/Passes.h"
using namespace mlir;
using namespace circt;
using namespace ibis;
using namespace kanagawa;
/// Create a simple canonicalizer pass.
static std::unique_ptr<Pass> createSimpleCanonicalizerPass() {
@ -25,12 +25,12 @@ static std::unique_ptr<Pass> createSimpleCanonicalizerPass() {
return mlir::createCanonicalizerPass(config);
}
void circt::ibis::loadIbisLowLevelPassPipeline(mlir::PassManager &pm) {
void circt::kanagawa::loadKanagawaLowLevelPassPipeline(mlir::PassManager &pm) {
// Inner ref: We create an inner ref verification pass to initially validate
// the IR, as well as after all structure-changing passes.
// In the future, could consider hiding this behind a flag to reduce overhead.
pm.addPass(hw::createVerifyInnerRefNamespacePass());
pm.nest<ibis::DesignOp>().addPass(createContainerizePass());
pm.nest<kanagawa::DesignOp>().addPass(createContainerizePass());
pm.addPass(hw::createVerifyInnerRefNamespacePass());
// Pre-tunneling CSE pass. This ensures that duplicate get_port calls are
@ -38,7 +38,7 @@ void circt::ibis::loadIbisLowLevelPassPipeline(mlir::PassManager &pm) {
// twice.
pm.addPass(mlir::createCSEPass());
pm.nest<DesignOp>().addPass(
createTunnelingPass(IbisTunnelingOptions{"", ""}));
createTunnelingPass(KanagawaTunnelingOptions{"", ""}));
pm.addPass(hw::createVerifyInnerRefNamespacePass());
pm.addPass(createPortrefLoweringPass());
pm.addPass(createSimpleCanonicalizerPass());
@ -47,11 +47,11 @@ void circt::ibis::loadIbisLowLevelPassPipeline(mlir::PassManager &pm) {
pm.addPass(hw::createVerifyInnerRefNamespacePass());
}
void circt::ibis::loadIbisHighLevelPassPipeline(mlir::PassManager &pm) {
pm.nest<ibis::DesignOp>()
.nest<ibis::ClassOp>()
.nest<ibis::MethodOp>()
.addPass(ibis::createInlineSBlocksPass());
void circt::kanagawa::loadKanagawaHighLevelPassPipeline(mlir::PassManager &pm) {
pm.nest<kanagawa::DesignOp>()
.nest<kanagawa::ClassOp>()
.nest<kanagawa::MethodOp>()
.addPass(kanagawa::createInlineSBlocksPass());
pm.addPass(mlir::createMem2Reg());
// TODO @mortbopet: Add a verification pass to ensure that there are no more
@ -62,11 +62,11 @@ void circt::ibis::loadIbisHighLevelPassPipeline(mlir::PassManager &pm) {
// Now, perform SSA maximizations.
pm.addPass(circt::createMaximizeSSAPass());
// SSA maximal form achieved. Reconstruct the Ibis sblocks.
pm.nest<ibis::DesignOp>()
.nest<ibis::ClassOp>()
.nest<ibis::MethodOp>()
.addPass(ibis::createReblockPass());
pm.addPass(ibis::createArgifyBlocksPass());
// SSA maximal form achieved. Reconstruct the Kanagawa sblocks.
pm.nest<kanagawa::DesignOp>()
.nest<kanagawa::ClassOp>()
.nest<kanagawa::MethodOp>()
.addPass(kanagawa::createReblockPass());
pm.addPass(kanagawa::createArgifyBlocksPass());
pm.addPass(createSimpleCanonicalizerPass());
}

View File

@ -1,4 +1,4 @@
//===- IbisPortrefLowering.cpp - Implementation of PortrefLowering --------===//
//===- KanagawaPortrefLowering.cpp - Implementation of PortrefLowering ----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,32 +6,32 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "mlir/Pass/Pass.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "mlir/IR/Builders.h"
#include "mlir/Transforms/DialectConversion.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/Debug.h"
#define DEBUG_TYPE "ibis-lower-portrefs"
#define DEBUG_TYPE "kanagawa-lower-portrefs"
namespace circt {
namespace ibis {
#define GEN_PASS_DEF_IBISPORTREFLOWERING
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
} // namespace ibis
namespace kanagawa {
#define GEN_PASS_DEF_KANAGAWAPORTREFLOWERING
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace kanagawa
} // namespace circt
using namespace mlir;
using namespace circt;
using namespace ibis;
using namespace kanagawa;
namespace {
@ -57,17 +57,19 @@ public:
std::distance(portrefUsers.begin(), portrefUsers.end());
if (nPortrefUsers != 1)
return rewriter.notifyMatchFailure(
op, "expected a single ibis.port.read as the only user of the input "
"port reference, but found multiple readers - please run CSE "
"prior to this pass");
op,
"expected a single kanagawa.port.read as the only user of the input "
"port reference, but found multiple readers - please run CSE "
"prior to this pass");
// A single PortReadOp should be present, which unwraps the portref<portref>
// into a portref.
PortReadOp portUnwrapper = dyn_cast<PortReadOp>(*portrefUsers.begin());
if (!portUnwrapper)
return rewriter.notifyMatchFailure(
op, "expected a single ibis.port.read as the only user of the input "
"port reference");
op,
"expected a single kanagawa.port.read as the only user of the input "
"port reference");
// Replace the inner portref + port access with a "raw" port.
OpBuilder::InsertionGuard g(rewriter);
@ -99,7 +101,7 @@ public:
// See https://github.com/llvm/circt/issues/6795.
portUnwrapper.getResult().replaceAllUsesWith(rawInput);
// Replace all ibis.port.read ops with a read of the new input.
// Replace all kanagawa.port.read ops with a read of the new input.
for (auto *portUser :
llvm::make_early_inc_range(portUnwrapper.getResult().getUsers())) {
PortReadOp portReader = dyn_cast<PortReadOp>(portUser);
@ -138,7 +140,7 @@ public:
if (writeOp && writeOp.getPort() == op.getResult()) {
if (portWrapper)
return rewriter.notifyMatchFailure(
op, "expected a single ibis.port.write to wrap the output "
op, "expected a single kanagawa.port.write to wrap the output "
"portref, but found multiple");
portWrapper = writeOp;
break;
@ -147,7 +149,7 @@ public:
if (!portWrapper)
return rewriter.notifyMatchFailure(
op, "expected an ibis.port.write to wrap the output portref");
op, "expected an kanagawa.port.write to wrap the output portref");
OpBuilder::InsertionGuard g(rewriter);
rewriter.setInsertionPoint(op);
@ -213,7 +215,7 @@ class GetPortConversionPattern : public OpConversionPattern<GetPortOp> {
if (!getPortWrapper)
return rewriter.notifyMatchFailure(
op, "expected an ibis.port.write to wrap the get_port result");
op, "expected an kanagawa.port.write to wrap the get_port result");
wrapper = getPortWrapper;
LLVM_DEBUG(llvm::dbgs() << "Found wrapper: " << *wrapper);
if (innerDirection == Direction::Input) {
@ -247,25 +249,27 @@ class GetPortConversionPattern : public OpConversionPattern<GetPortOp> {
if (!getPortUnwrapper)
return rewriter.notifyMatchFailure(
op, "expected an ibis.port.read to unwrap the get_port result");
op, "expected an kanagawa.port.read to unwrap the get_port result");
wrapper = getPortUnwrapper;
LLVM_DEBUG(llvm::dbgs() << "Found unwrapper: " << *wrapper);
if (innerDirection == Direction::Input) {
// In this situation, we're retrieving an input port that is sent as an
// output of the container: %rr = ibis.get_port %c %c_in :
// !ibis.scoperef<...> -> !ibis.portref<out !ibis.portref<in T>>
// output of the container: %rr = kanagawa.get_port %c %c_in :
// !kanagawa.scoperef<...> -> !kanagawa.portref<out !kanagawa.portref<in
// T>>
//
// Thus we expect one of these cases:
// (always). a read op which unwraps the portref<out portref<in T>> into
// a portref<in T>
// %r = ibis.port.read %rr : !ibis.portref<out !ibis.portref<in T>>
// %r = kanagawa.port.read %rr : !kanagawa.portref<out
// !kanagawa.portref<in T>>
// either:
// 1. A write to %r which drives the target input port
// ibis.port.write %r, %someValue : !ibis.portref<in T>
// kanagawa.port.write %r, %someValue : !kanagawa.portref<in T>
// 2. A write using %r which forwards the input port reference
// ibis.port.write %r_fw, %r : !ibis.portref<out !ibis.portref<in
// T>>
// kanagawa.port.write %r_fw, %r : !kanagawa.portref<out
// !kanagawa.portref<in T>>
//
PortWriteOp portDriver;
PortWriteOp portForwardingDriver;
@ -278,16 +282,18 @@ class GetPortConversionPattern : public OpConversionPattern<GetPortOp> {
if (isForwarding) {
if (portForwardingDriver)
return rewriter.notifyMatchFailure(
op, "expected a single ibis.port.write to use the unwrapped "
"get_port result, but found multiple");
op,
"expected a single kanagawa.port.write to use the unwrapped "
"get_port result, but found multiple");
portForwardingDriver = writeOp;
LLVM_DEBUG(llvm::dbgs()
<< "Found forwarding driver: " << *portForwardingDriver);
} else {
if (portDriver)
return rewriter.notifyMatchFailure(
op, "expected a single ibis.port.write to use the unwrapped "
"get_port result, but found multiple");
op,
"expected a single kanagawa.port.write to use the unwrapped "
"get_port result, but found multiple");
portDriver = writeOp;
LLVM_DEBUG(llvm::dbgs() << "Found driver: " << *portDriver);
}
@ -295,8 +301,9 @@ class GetPortConversionPattern : public OpConversionPattern<GetPortOp> {
if (!portDriver && !portForwardingDriver)
return rewriter.notifyMatchFailure(
op, "expected an ibis.port.write to drive the unwrapped get_port "
"result");
op,
"expected an kanagawa.port.write to drive the unwrapped get_port "
"result");
Value portDriverValue;
if (portForwardingDriver) {
@ -333,13 +340,15 @@ class GetPortConversionPattern : public OpConversionPattern<GetPortOp> {
rewriter.create<PortWriteOp>(op.getLoc(), rawPort, portDriverValue);
} else {
// In this situation, we're retrieving an output port that is sent as an
// output of the container: %rr = ibis.get_port %c %c_in :
// !ibis.scoperef<...> -> !ibis.portref<out !ibis.portref<out T>>
// output of the container: %rr = kanagawa.get_port %c %c_in :
// !kanagawa.scoperef<...> -> !kanagawa.portref<out
// !kanagawa.portref<out T>>
//
// Thus we expect two ops to be present:
// 1. a read op which unwraps the portref<out portref<in T>> into a
// portref<in T>
// %r = ibis.port.read %rr : !ibis.portref<out !ibis.portref<in T>>
// %r = kanagawa.port.read %rr : !kanagawa.portref<out
// !kanagawa.portref<in T>>
// 2. one (or multiple, if not CSEd)
//
// We then replace the read op with the actual output port of the
@ -366,7 +375,8 @@ class GetPortConversionPattern : public OpConversionPattern<GetPortOp> {
};
struct PortrefLoweringPass
: public circt::ibis::impl::IbisPortrefLoweringBase<PortrefLoweringPass> {
: public circt::kanagawa::impl::KanagawaPortrefLoweringBase<
PortrefLoweringPass> {
void runOnOperation() override;
};
@ -376,7 +386,7 @@ void PortrefLoweringPass::runOnOperation() {
auto *ctx = &getContext();
ConversionTarget target(*ctx);
target.addIllegalOp<InputPortOp, OutputPortOp>();
target.addLegalDialect<IbisDialect>();
target.addLegalDialect<KanagawaDialect>();
// Ports are legal when they do not have portref types anymore.
target.addDynamicallyLegalOp<InputPortOp, OutputPortOp>([&](auto op) {
@ -402,6 +412,6 @@ void PortrefLoweringPass::runOnOperation() {
signalPassFailure();
}
std::unique_ptr<Pass> circt::ibis::createPortrefLoweringPass() {
std::unique_ptr<Pass> circt::kanagawa::createPortrefLoweringPass() {
return std::make_unique<PortrefLoweringPass>();
}

View File

@ -1,4 +1,4 @@
//===- IbisPrepareScheduling.cpp - Prepares ibis static blocks for scheduling //
//===- KanagawaPrepareScheduling.cpp - Prepares static blocks for scheduling =//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,15 +6,15 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "mlir/Pass/Pass.h"
#include "circt/Dialect/Comb/CombOps.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "circt/Dialect/Pipeline/PipelineOps.h"
#include "circt/Dialect/SSP/SSPOps.h"
@ -23,19 +23,19 @@
#include "mlir/Transforms/DialectConversion.h"
namespace circt {
namespace ibis {
#define GEN_PASS_DEF_IBISPREPARESCHEDULING
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
} // namespace ibis
namespace kanagawa {
#define GEN_PASS_DEF_KANAGAWAPREPARESCHEDULING
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace kanagawa
} // namespace circt
using namespace circt;
using namespace ibis;
using namespace kanagawa;
namespace {
struct PrepareSchedulingPass
: public circt::ibis::impl::IbisPrepareSchedulingBase<
: public circt::kanagawa::impl::KanagawaPrepareSchedulingBase<
PrepareSchedulingPass> {
void runOnOperation() override;
@ -55,7 +55,7 @@ PrepareSchedulingPass::prepareSBlock(IsolatedStaticBlockOp sblock) {
Location loc = sblock.getLoc();
Block *bodyBlock = sblock.getBodyBlock();
auto b = OpBuilder::atBlockBegin(bodyBlock);
auto ph = b.create<ibis::PipelineHeaderOp>(loc);
auto ph = b.create<kanagawa::PipelineHeaderOp>(loc);
// Create a pipeline.unscheduled operation which returns the same types
// as that returned by the sblock.
@ -127,7 +127,7 @@ LogicalResult PrepareSchedulingPass::attachOperatorTypes(
// Attach the operator lib attribute
pipeline->setAttr(
"operator_lib",
FlatSymbolRefAttr::get(pipeline.getContext(), kIbisOperatorLibName));
FlatSymbolRefAttr::get(pipeline.getContext(), kKanagawaOperatorLibName));
return success();
}
@ -138,6 +138,6 @@ void PrepareSchedulingPass::runOnOperation() {
return signalPassFailure();
}
std::unique_ptr<Pass> circt::ibis::createPrepareSchedulingPass() {
std::unique_ptr<Pass> circt::kanagawa::createPrepareSchedulingPass() {
return std::make_unique<PrepareSchedulingPass>();
}

View File

@ -1,4 +1,4 @@
//===- IbisReblockPass.cpp ------------------------------------------------===//
//===- KanagawaReblockPass.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,34 +6,36 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "mlir/Pass/Pass.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "circt/Transforms/Passes.h"
#include "mlir/Transforms/DialectConversion.h"
namespace circt {
namespace ibis {
#define GEN_PASS_DEF_IBISREBLOCK
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
} // namespace ibis
namespace kanagawa {
#define GEN_PASS_DEF_KANAGAWAREBLOCK
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace kanagawa
} // namespace circt
using namespace circt;
using namespace ibis;
using namespace kanagawa;
namespace {
struct ReblockPass : public circt::ibis::impl::IbisReblockBase<ReblockPass> {
struct ReblockPass
: public circt::kanagawa::impl::KanagawaReblockBase<ReblockPass> {
void runOnOperation() override;
// Transforms an `ibis.sblock.inline.begin/end` scope into an `ibis.sblock`.
// Transforms an `kanagawa.sblock.inline.begin/end` scope into an
// `kanagawa.sblock`.
LogicalResult reblock(ArrayRef<Operation *> ops, Operation *blockTerminator);
/// Track ops that should be erased.
@ -44,7 +46,7 @@ struct ReblockPass : public circt::ibis::impl::IbisReblockBase<ReblockPass> {
// operations should be closed.
static bool isSBlockTerminator(Operation *op) {
return op->hasTrait<OpTrait::IsTerminator>() ||
isa<ibis::InlineStaticBlockEndOp, InlineStaticBlockBeginOp>(op);
isa<kanagawa::InlineStaticBlockEndOp, InlineStaticBlockBeginOp>(op);
}
} // anonymous namespace
@ -76,7 +78,7 @@ LogicalResult ReblockPass::reblock(ArrayRef<Operation *> ops,
// Determine which values we need to return from within the block scope.
// This is done by collecting all values defined within the start/end scope,
// and recording uses that exist outside of the scope.
ibis::InlineStaticBlockBeginOp blockBeginOp;
kanagawa::InlineStaticBlockBeginOp blockBeginOp;
if (isa<InlineStaticBlockEndOp>(blockTerminator)) {
blockBeginOp = dyn_cast<InlineStaticBlockBeginOp>(ops.front());
assert(blockBeginOp &&
@ -118,17 +120,17 @@ LogicalResult ReblockPass::reblock(ArrayRef<Operation *> ops,
}
auto b = OpBuilder(beginOp);
auto ibisBlock =
auto kanagawaBlock =
b.create<StaticBlockOp>(beginOp->getLoc(), blockRetTypes, ValueRange{});
// The new `ibis.sblock` should inherit the attributes of the block begin op,
// if provided.
// The new `kanagawa.sblock` should inherit the attributes of the block begin
// op, if provided.
if (blockBeginOp)
ibisBlock->setAttrs(blockBeginOp->getAttrs());
kanagawaBlock->setAttrs(blockBeginOp->getAttrs());
// Move operations into the `ibis.sblock` op.
// Move operations into the `kanagawa.sblock` op.
BlockReturnOp blockReturn =
cast<BlockReturnOp>(ibisBlock.getBodyBlock()->getTerminator());
cast<BlockReturnOp>(kanagawaBlock.getBodyBlock()->getTerminator());
for (auto &op :
llvm::make_early_inc_range(llvm::make_range(startIt, terminatorIt)))
@ -140,7 +142,7 @@ LogicalResult ReblockPass::reblock(ArrayRef<Operation *> ops,
// Replace the uses of the returned values outside of the block with the
// block return values.
for (auto [blockRet, innerDefAndUses] :
llvm::zip(ibisBlock.getResults(), returnValueUses)) {
llvm::zip(kanagawaBlock.getResults(), returnValueUses)) {
auto &uses = std::get<1>(innerDefAndUses);
for (OpOperand *use : uses)
use->set(blockRet);
@ -155,6 +157,6 @@ LogicalResult ReblockPass::reblock(ArrayRef<Operation *> ops,
return success();
}
std::unique_ptr<Pass> circt::ibis::createReblockPass() {
std::unique_ptr<Pass> circt::kanagawa::createReblockPass() {
return std::make_unique<ReblockPass>();
}

View File

@ -1,4 +1,4 @@
//===- IbisTunneling.cpp - Implementation of tunneling --------------------===//
//===- KanagawaTunneling.cpp - Implementation of tunneling ----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Ibis/IbisTypes.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaTypes.h"
#include "circt/Support/InstanceGraph.h"
#include "mlir/IR/Builders.h"
@ -18,15 +18,15 @@
#include "llvm/ADT/TypeSwitch.h"
namespace circt {
namespace ibis {
#define GEN_PASS_DEF_IBISTUNNELING
#include "circt/Dialect/Ibis/IbisPasses.h.inc"
} // namespace ibis
namespace kanagawa {
#define GEN_PASS_DEF_KANAGAWATUNNELING
#include "circt/Dialect/Kanagawa/KanagawaPasses.h.inc"
} // namespace kanagawa
} // namespace circt
using namespace mlir;
using namespace circt;
using namespace circt::ibis;
using namespace circt::kanagawa;
using namespace circt::igraph;
namespace {
@ -49,7 +49,7 @@ struct PortInfo {
struct Tunneler {
public:
Tunneler(const IbisTunnelingOptions &options, PathOp op,
Tunneler(const KanagawaTunnelingOptions &options, PathOp op,
ConversionPatternRewriter &rewriter, InstanceGraph &ig);
// A mapping between requested port names from a ScopeRef and the actual
@ -67,7 +67,7 @@ private:
llvm::ArrayRef<PathStepAttr> path,
PortRefMapping &mapping);
// "Port forwarding" check - ibis.get_port specifies the intended
// "Port forwarding" check - kanagawa.get_port specifies the intended
// direction which a port is accessed by from within the hierarchy.
// If the intended direction is not the same as the actual port
// direction, we need to insert a wire to flip the direction of the
@ -95,7 +95,7 @@ private:
PathOp op;
ConversionPatternRewriter &rewriter;
InstanceGraph &ig;
const IbisTunnelingOptions &options;
const KanagawaTunnelingOptions &options;
mlir::StringAttr pathName;
llvm::SmallVector<PathStepAttr> path;
@ -108,12 +108,12 @@ private:
FlatSymbolRefAttr targetName;
};
Tunneler::Tunneler(const IbisTunnelingOptions &options, PathOp op,
Tunneler::Tunneler(const KanagawaTunnelingOptions &options, PathOp op,
ConversionPatternRewriter &rewriter, InstanceGraph &ig)
: op(op), rewriter(rewriter), ig(ig), options(options) {
llvm::copy(op.getPathAsRange(), std::back_inserter(path));
assert(!path.empty() &&
"empty paths should never occur - illegal for ibis.path ops");
"empty paths should never occur - illegal for kanagawa.path ops");
target = path.back();
targetName = target.getChild();
}
@ -148,7 +148,7 @@ LogicalResult Tunneler::go() {
auto getPortOp = dyn_cast<GetPortOp>(user);
if (!getPortOp)
return user->emitOpError() << "unknown user of a PathOp result - "
"tunneling only supports ibis.get_port";
"tunneling only supports kanagawa.get_port";
portInfos.push_back(
PortInfo{getPortOp.getPortSymbolAttr().getAttr(), getPortOp});
}
@ -210,7 +210,7 @@ Value Tunneler::portForwardIfNeeded(PortOpInterface actualPort,
rewriter.setInsertionPointAfter(actualPort);
// If the requested direction was an input, this means that someone tried
// to write to an output port. We need to insert an ibis.wire.input that
// to write to an output port. We need to insert an kanagawa.wire.input that
// provides a writeable input port, and assign the wire output to the
// output port.
if (requestedDir == Direction::Input) {
@ -224,7 +224,7 @@ Value Tunneler::portForwardIfNeeded(PortOpInterface actualPort,
}
// If the requested direction was an output, this means that someone tried
// to read from an input port. We need to insert an ibis.wire.output that
// to read from an input port. We need to insert an kanagawa.wire.output that
// provides a readable output port, and read the input port as the value
// of the wire.
Value inputValue =
@ -238,7 +238,8 @@ Value Tunneler::portForwardIfNeeded(PortOpInterface actualPort,
}
// Lookup an instance in the parent op. If the parent op is a symbol table, will
// use that - else, scan the ibis.container.instance operations in the parent.
// use that - else, scan the kanagawa.container.instance operations in the
// parent.
static FailureOr<ContainerInstanceOp> locateInstanceIn(Operation *parentOp,
FlatSymbolRefAttr name) {
if (parentOp->hasTrait<OpTrait::SymbolTable>()) {
@ -393,7 +394,7 @@ LogicalResult Tunneler::tunnelUp(InstanceGraphNode *currentContainer,
class TunnelingConversionPattern : public OpConversionPattern<PathOp> {
public:
TunnelingConversionPattern(MLIRContext *context, InstanceGraph &ig,
IbisTunnelingOptions options)
KanagawaTunnelingOptions options)
: OpConversionPattern<PathOp>(context), ig(ig),
options(std::move(options)) {}
@ -405,12 +406,12 @@ public:
protected:
InstanceGraph &ig;
IbisTunnelingOptions options;
KanagawaTunnelingOptions options;
};
struct TunnelingPass
: public circt::ibis::impl::IbisTunnelingBase<TunnelingPass> {
using IbisTunnelingBase<TunnelingPass>::IbisTunnelingBase;
: public circt::kanagawa::impl::KanagawaTunnelingBase<TunnelingPass> {
using KanagawaTunnelingBase<TunnelingPass>::KanagawaTunnelingBase;
void runOnOperation() override;
};
@ -426,7 +427,7 @@ void TunnelingPass::runOnOperation() {
RewritePatternSet patterns(ctx);
patterns.add<TunnelingConversionPattern>(
ctx, ig, IbisTunnelingOptions{readSuffix, writeSuffix});
ctx, ig, KanagawaTunnelingOptions{readSuffix, writeSuffix});
if (failed(
applyPartialConversion(getOperation(), target, std::move(patterns))))
@ -434,6 +435,6 @@ void TunnelingPass::runOnOperation() {
}
std::unique_ptr<Pass>
circt::ibis::createTunnelingPass(const IbisTunnelingOptions &options) {
circt::kanagawa::createTunnelingPass(const KanagawaTunnelingOptions &options) {
return std::make_unique<TunnelingPass>(options);
}

2
llvm

@ -1 +1 @@
Subproject commit 3cc852ece438a63e7b09d1c84a81d21598454e1a
Subproject commit 8193832fb988e3df1e8e726634783805dca8d9b6

View File

@ -33,7 +33,7 @@ set(CIRCT_TEST_DEPENDS
handshake-runner
firtool
hlstool
ibistool
kanagawatool
om-linker
)

View File

@ -1,30 +0,0 @@
// RUN: circt-opt --ibis-argify-blocks %s | FileCheck %s
// CHECK-LABEL: ibis.class sym @Argify {
// CHECK-NEXT: %this = ibis.this <@foo::@Argify>
// CHECK-NEXT: ibis.method @foo() -> () {
// CHECK-NEXT: %c32_i32 = hw.constant 32 : i32
// CHECK-NEXT: %0:2 = ibis.sblock.isolated (%arg0 : i32 = %c32_i32) -> (i32, i32) {
// CHECK-NEXT: %c31_i32 = hw.constant 31 : i32
// CHECK-NEXT: %1 = arith.addi %arg0, %c31_i32 : i32
// CHECK-NEXT: ibis.sblock.return %1, %arg0 : i32, i32
// CHECK-NEXT: }
// CHECK-NEXT: ibis.return
// CHECK-NEXT: }
// CHECK-NEXT: }
ibis.design @foo {
ibis.class sym @Argify {
%this = ibis.this <@foo::@Argify>
ibis.method @foo() {
%c32 = hw.constant 32 : i32
%0:2 = ibis.sblock() -> (i32, i32) {
%c31 = hw.constant 31 : i32
%res = arith.addi %c31, %c32 : i32
ibis.sblock.return %res, %c32 : i32, i32
}
ibis.return
}
}
}

View File

@ -1,85 +0,0 @@
// RUN: circt-opt --allow-unregistered-dialect --split-input-file --ibis-clean-selfdrivers %s | FileCheck %s
ibis.design @D {
// CHECK-LABEL: ibis.container sym @C {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@C>
// CHECK: %[[VAL_1:.*]] = hw.wire %[[VAL_2:.*]] : i1
// CHECK: %[[VAL_3:.*]] = ibis.port.output "out" sym @out : i1
// CHECK: %[[VAL_2]] = hw.constant true
// CHECK: ibis.port.write %[[VAL_3]], %[[VAL_1]] : !ibis.portref<out i1>
// CHECK: }
ibis.container sym @C {
%this = ibis.this <@D::@C>
%in = ibis.port.input "in" sym @in : i1
%out = ibis.port.output "out" sym @out : i1
%true = hw.constant 1 : i1
ibis.port.write %in, %true : !ibis.portref<in i1>
%v = ibis.port.read %in : !ibis.portref<in i1>
ibis.port.write %out, %v : !ibis.portref<out i1>
}
}
// -----
ibis.design @D {
// CHECK-LABEL: ibis.container sym @Selfdriver {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@Selfdriver>
// CHECK: %[[VAL_1:.*]] = hw.wire %[[VAL_2:.*]] : i1
// CHECK: %[[VAL_3:.*]] = ibis.port.output "myIn" sym @in : i1
// CHECK: ibis.port.write %[[VAL_3]], %[[VAL_1]] : !ibis.portref<out i1>
// CHECK: %[[VAL_2]] = hw.constant true
// CHECK: }
// CHECK-LABEL: ibis.container sym @ParentReader {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@ParentReader>
// CHECK: %[[VAL_1:.*]] = ibis.container.instance @selfdriver, <@D::@Selfdriver>
// CHECK: %[[VAL_2:.*]] = ibis.get_port %[[VAL_1]], @in : !ibis.scoperef<@D::@Selfdriver> -> !ibis.portref<out i1>
// CHECK: %[[VAL_3:.*]] = ibis.port.read %[[VAL_2]] : !ibis.portref<out i1>
// CHECK: }
ibis.container sym @Selfdriver {
%this = ibis.this <@D::@Selfdriver>
%in = ibis.port.input "myIn" sym @in : i1
%true = hw.constant 1 : i1
ibis.port.write %in, %true : !ibis.portref<in i1>
}
ibis.container sym @ParentReader {
%this = ibis.this <@D::@ParentReader>
%selfdriver = ibis.container.instance @selfdriver, <@D::@Selfdriver>
%in_ref = ibis.get_port %selfdriver, @in : !ibis.scoperef<@D::@Selfdriver> -> !ibis.portref<out i1>
%in = ibis.port.read %in_ref : !ibis.portref<out i1>
}
}
// -----
ibis.design @D {
ibis.container sym @Foo {
%this = ibis.this <@D::@Foo>
%in = ibis.port.input "in" sym @in : i1
}
// CHECK-LABEL: ibis.container sym @ParentReaderWriter {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@ParentReaderWriter>
// CHECK: %[[VAL_1:.*]] = ibis.container.instance @f, <@D::@Foo>
// CHECK: %[[VAL_2:.*]] = ibis.get_port %[[VAL_1]], @in : !ibis.scoperef<@D::@Foo> -> !ibis.portref<in i1>
// CHECK: "foo.bar"(%[[VAL_3:.*]]) : (i1) -> ()
// CHECK: %[[VAL_3]] = hw.constant true
// CHECK: ibis.port.write %[[VAL_2]], %[[VAL_3]] : !ibis.portref<in i1>
// CHECK: }
ibis.container sym @ParentReaderWriter {
%this = ibis.this <@D::@ParentReaderWriter>
%f = ibis.container.instance @f, <@D::@Foo>
%in_wr_ref = ibis.get_port %f, @in : !ibis.scoperef<@D::@Foo> -> !ibis.portref<in i1>
%in_rd_ref = ibis.get_port %f, @in : !ibis.scoperef<@D::@Foo> -> !ibis.portref<out i1>
%v = ibis.port.read %in_rd_ref : !ibis.portref<out i1>
"foo.bar"(%v) : (i1) -> ()
%true = hw.constant 1 : i1
ibis.port.write %in_wr_ref, %true : !ibis.portref<in i1>
}
}

View File

@ -1,38 +0,0 @@
// RUN: circt-opt --pass-pipeline='builtin.module(ibis.design(ibis-containerize))' %s | FileCheck %s
ibis.design @foo {
// CHECK-LABEL: ibis.container sym @A_B
// CHECK-LABEL: ibis.container "MyClassName" sym @MyClass
// CHECK-LABEL: ibis.container sym @A_B_0
// CHECK-LABEL: ibis.container sym @A_C
// CHECK-LABEL: ibis.container sym @A {
// CHECK: %[[VAL_0:.*]] = ibis.this <@foo::@A>
// CHECK: ibis.port.input "A_in" sym @A_in : i1
// CHECK: %[[VAL_1:.*]] = ibis.container.instance @myClass, <@foo::@MyClass>
// CHECK: %[[VAL_2:.*]] = ibis.container.instance @A_B_0, <@foo::@A_B_0>
// CHECK: %[[VAL_3:.*]] = ibis.container.instance @A_C, <@foo::@A_C>
// This container will alias with the @B inside @A, and thus checks the
// name uniquing logic.
ibis.container sym @A_B {
%this = ibis.this <@foo::@A_B>
}
ibis.class "MyClassName" sym @MyClass {
%this = ibis.this <@foo::@MyClass>
}
ibis.class sym @A {
%this = ibis.this <@foo::@A>
ibis.port.input "A_in" sym @A_in : i1
%myClass = ibis.instance @myClass, <@foo::@MyClass>
ibis.container sym @B {
%B_this = ibis.this <@foo::@B>
}
ibis.container sym @C {
%C_this = ibis.this <@foo::@C>
}
}
}

View File

@ -1,178 +0,0 @@
// RUN: circt-opt --split-input-file --ibis-convert-containers-to-hw %s | FileCheck %s
ibis.design @D {
// CHECK: hw.module @D_MyB(in %in_foo : i1 {inputAttr}, out out_foo : i1 {outputAttr}) {
// CHECK: hw.output %in_foo : i1
// CHECK: }
// CHECK: hw.module @D_AccessSibling(in %p_b_out_foo : i1, out p_b_in_foo : i1) {
// CHECK: hw.output %p_b_out_foo : i1
// CHECK: }
// CHECK: hw.module @Parent() {
// CHECK: %a.p_b_in_foo = hw.instance "a" @D_AccessSibling(p_b_out_foo: %b.out_foo: i1) -> (p_b_in_foo: i1)
// CHECK: %b.out_foo = hw.instance "b" @D_MyB(in_foo: %a.p_b_in_foo: i1) -> (out_foo: i1)
// CHECK: hw.output
// CHECK: }
ibis.container "MyB" sym @B {
%this = ibis.this <@D::@B>
// Test different port names vs. symbol names
%in = ibis.port.input "in_foo" sym @in : i1 {"inputAttr"}
%out = ibis.port.output "out_foo" sym @out : i1 {"outputAttr"}
// Loopback.
%v = ibis.port.read %in : !ibis.portref<in i1>
ibis.port.write %out, %v : !ibis.portref<out i1>
}
ibis.container sym @AccessSibling {
%this = ibis.this <@D::@AccessSibling>
%p_b_out = ibis.port.input "p_b_out_foo" sym @p_b_out : i1
%p_b_in = ibis.port.output "p_b_in_foo" sym @p_b_in : i1
ibis.port.write %p_b_in, %p_b_out.val : !ibis.portref<out i1>
%p_b_out.val = ibis.port.read %p_b_out : !ibis.portref<in i1>
}
ibis.container sym @Parent top_level {
%this = ibis.this <@D::@Parent>
%a = ibis.container.instance @a, <@D::@AccessSibling>
%a.p_b_out.ref = ibis.get_port %a, @p_b_out : !ibis.scoperef<@D::@AccessSibling> -> !ibis.portref<in i1>
%b.out.ref.val = ibis.port.read %b.out.ref : !ibis.portref<out i1>
ibis.port.write %a.p_b_out.ref, %b.out.ref.val : !ibis.portref<in i1>
%a.p_b_in.ref = ibis.get_port %a, @p_b_in : !ibis.scoperef<@D::@AccessSibling> -> !ibis.portref<out i1>
%a.p_b_in.ref.val = ibis.port.read %a.p_b_in.ref : !ibis.portref<out i1>
ibis.port.write %b.in.ref, %a.p_b_in.ref.val : !ibis.portref<in i1>
%b = ibis.container.instance @b, <@D::@B>
%b.out.ref = ibis.get_port %b, @out : !ibis.scoperef<@D::@B> -> !ibis.portref<out i1>
%b.in.ref = ibis.get_port %b, @in : !ibis.scoperef<@D::@B> -> !ibis.portref<in i1>
}
}
// -----
// Test that we can instantiate and get ports of a container from a hw.module.
ibis.design @D {
// CHECK: hw.module @D_C(in %in_foo : i1, out out_foo : i1) {
// CHECK: hw.output %in_foo : i1
// CHECK: }
// CHECK: hw.module @Top() {
// CHECK: %c.out_foo = hw.instance "c" @D_C(in_foo: %c.out_foo: i1) -> (out_foo: i1)
// CHECK: hw.output
// CHECK: }
ibis.container sym @C {
%this = ibis.this <@D::@C>
%in = ibis.port.input "in_foo" sym @in : i1
%out = ibis.port.output "out_foo" sym @out : i1
%v = ibis.port.read %in : !ibis.portref<in i1>
ibis.port.write %out, %v : !ibis.portref<out i1>
}
}
hw.module @Top() {
%c = ibis.container.instance @c, <@D::@C>
%in = ibis.get_port %c, @in : !ibis.scoperef<@D::@C> -> !ibis.portref<in i1>
%out = ibis.get_port %c, @out : !ibis.scoperef<@D::@C> -> !ibis.portref<out i1>
%v = ibis.port.read %out : !ibis.portref<out i1>
ibis.port.write %in, %v : !ibis.portref<in i1>
}
// -----
// Test that we can also move non-ibis ops
ibis.design @D {
// CHECK-LABEL: hw.module @D_Inst(out out : i1) {
// CHECK: %[[VAL_0:.*]] = hw.constant true
// CHECK: hw.output %[[VAL_0]] : i1
// CHECK: }
// CHECK-LABEL: hw.module @D_Top() {
// CHECK: %[[VAL_0:.*]] = hw.instance "myInst" @D_Inst() -> (out: i1)
// CHECK: %[[VAL_1:.*]] = hw.constant true
// CHECK: %[[VAL_2:.*]] = comb.and bin %[[VAL_1]], %[[VAL_0]] : i1
// CHECK: hw.output
// CHECK: }
ibis.container sym @Inst {
%this = ibis.this <@D::@Inst>
%out = ibis.port.output "out" sym @out : i1
%true = hw.constant 1 : i1
ibis.port.write %out, %true : !ibis.portref<out i1>
}
ibis.container sym @Top {
%this = ibis.this <@D::@Top>
%myInst = ibis.container.instance @myInst, <@D::@Inst>
%true = hw.constant 1 : i1
%out.ref = ibis.get_port %myInst, @out : !ibis.scoperef<@D::@Inst> -> !ibis.portref<out i1>
%out.v = ibis.port.read %out.ref : !ibis.portref<out i1>
%blake = comb.and bin %true, %out.v : i1
}
}
// -----
// Test that we can unique duplicate port names.
ibis.design @D {
// CHECK: hw.module @D_Top(in %clk : i1, in %clk_0 : i1, out out : i1, out out_0 : i1) {
// CHECK: hw.output %clk, %clk_0 : i1, i1
ibis.container sym @Top {
%this = ibis.this <@D::@Top>
%clk1 = ibis.port.input "clk" sym @clk1 : i1
%clk2 = ibis.port.input "clk" sym @clk2 : i1
%out1 = ibis.port.output "out" sym @out1 : i1
%out2 = ibis.port.output "out" sym @out2 : i1
%v1 = ibis.port.read %clk1 : !ibis.portref<in i1>
%v2 = ibis.port.read %clk2 : !ibis.portref<in i1>
ibis.port.write %out1, %v1 : !ibis.portref<out i1>
ibis.port.write %out2, %v2 : !ibis.portref<out i1>
}
}
// -----
// Test that we can de-alias module names.
// CHECK: hw.module @D_Foo_0() {
// CHECK: hw.output
// CHECK: }
// CHECK: hw.module @Foo_0() {
// CHECK: hw.output
// CHECK: }
// CHECK: hw.module.extern @D_Foo(in %theExternModule : i1)
// CHECK: hw.module.extern @Foo(in %theExternModule : i1)
ibis.design @D {
ibis.container "Foo" sym @A {
%this = ibis.this <@D::@A>
}
ibis.container "Foo" sym @B top_level {
%this = ibis.this <@D::@B>
}
}
hw.module.extern @D_Foo(in %theExternModule : i1)
hw.module.extern @Foo(in %theExternModule : i1)
// -----
// Test that containers with names that alias with the design op are not
// de-aliased.
// CHECK: hw.module @D
ibis.design @D {
ibis.container "D" sym @D top_level {
%this = ibis.this <@D::@D>
}
}

View File

@ -1,33 +0,0 @@
// RUN: circt-opt --pass-pipeline='builtin.module(ibis.design(ibis.class(ibis-convert-handshake-to-dc)))' %s | FileCheck %s
// Actual handshake-to-dc conversion is tested in the respective pass tests.
// This file just tests the ibis-specific hooks.
// CHECK-LABEL: ibis.class sym @ToDC {
// CHECK: %[[VAL_0:.*]] = ibis.this <@foo::@ToDC>
// CHECK: ibis.method.df @foo(%[[VAL_1:.*]]: !dc.value<i32>) -> !dc.value<i32> {
// CHECK: %[[VAL_2:.*]], %[[VAL_3:.*]] = dc.unpack %[[VAL_1]] : !dc.value<i32>
// CHECK: %[[VAL_4:.*]]:2 = dc.fork [2] %[[VAL_2]]
// CHECK: %[[VAL_5:.*]] = dc.pack %[[VAL_4]]#0, %[[VAL_3]] : i32
// CHECK: %[[VAL_6:.*]] = dc.pack %[[VAL_4]]#1, %[[VAL_3]] : i32
// CHECK: %[[VAL_7:.*]] = ibis.sblock.dc (%[[VAL_8:.*]] : !dc.value<i32> = %[[VAL_5]], %[[VAL_9:.*]] : !dc.value<i32> = %[[VAL_6]]) -> !dc.value<i32> {
// CHECK: %[[VAL_10:.*]] = arith.addi %[[VAL_8]], %[[VAL_9]] : i32
// CHECK: ibis.sblock.return %[[VAL_10]] : i32
// CHECK: }
// CHECK: ibis.return %[[VAL_7]] : !dc.value<i32>
// CHECK: }
// CHECK: }
ibis.design @foo {
ibis.class sym @ToDC {
%this = ibis.this <@foo::@ToDC>
ibis.method.df @foo(%arg0: i32) -> (i32) {
%o0, %o1 = handshake.fork [2] %arg0 : i32
%1 = ibis.sblock.isolated(%a0 : i32 = %o0, %a1 : i32 = %o1) -> i32 {
%res = arith.addi %a0, %a1 : i32
ibis.sblock.return %res : i32
}
ibis.return %1 : i32
}
}
}

View File

@ -1,64 +0,0 @@
// RUN: circt-opt --pass-pipeline='builtin.module(ibis.design(ibis.class(ibis.method(ibis-inline-sblocks))))' \
// RUN: --allow-unregistered-dialect %s | FileCheck %s
ibis.design @foo {
// CHECK-LABEL: ibis.class sym @Inline1 {
// CHECK: %[[VAL_0:.*]] = ibis.this <@foo::@Inline1>
// CHECK: ibis.method @foo(%[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32) -> () {
// CHECK: ibis.sblock.inline.begin {maxThreads = 1 : i64}
// CHECK: %[[VAL_3:.*]] = "foo.op1"(%[[VAL_1]], %[[VAL_2]]) : (i32, i32) -> i32
// CHECK: ibis.sblock.inline.end
// CHECK: ibis.return
// CHECK: }
// CHECK: }
ibis.class sym @Inline1 {
%this = ibis.this <@foo::@Inline1>
ibis.method @foo(%a : i32, %b : i32) {
%0 = ibis.sblock() -> (i32) attributes {maxThreads = 1} {
%res = "foo.op1"(%a, %b) : (i32, i32) -> i32
ibis.sblock.return %res : i32
}
ibis.return
}
}
// CHECK-LABEL: ibis.class sym @Inline2 {
// CHECK: %[[VAL_0:.*]] = ibis.this <@foo::@Inline2>
// CHECK: ibis.method @foo(%[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32) -> () {
// CHECK: "foo.unused1"() : () -> ()
// CHECK: ibis.sblock.inline.begin {maxThreads = 1 : i64}
// CHECK: %[[VAL_3:.*]] = "foo.op1"(%[[VAL_1]], %[[VAL_2]]) : (i32, i32) -> i32
// CHECK: ibis.sblock.inline.end
// CHECK: "foo.unused2"() : () -> ()
// CHECK: cf.br ^bb1
// CHECK: ^bb1:
// CHECK: "foo.unused3"() : () -> ()
// CHECK: %[[VAL_4:.*]] = "foo.op2"(%[[VAL_3]], %[[VAL_1]]) : (i32, i32) -> i32
// CHECK: "foo.unused4"() : () -> ()
// CHECK: ibis.return
// CHECK: }
// CHECK: }
ibis.class sym @Inline2 {
%this = ibis.this <@foo::@Inline2>
ibis.method @foo(%a : i32, %b : i32) {
"foo.unused1"() : () -> ()
%0 = ibis.sblock() -> (i32) attributes {maxThreads = 1} {
%res = "foo.op1"(%a, %b) : (i32, i32) -> i32
ibis.sblock.return %res : i32
}
"foo.unused2"() : () -> ()
cf.br ^bb1
^bb1:
"foo.unused3"() : () -> ()
%1 = ibis.sblock() -> (i32) {
%res = "foo.op2"(%0, %a) : (i32, i32) -> i32
ibis.sblock.return %res : i32
}
"foo.unused4"() : () -> ()
ibis.return
}
}
}

View File

@ -1,37 +0,0 @@
// RUN: circt-opt --pass-pipeline='builtin.module(ibis.design(ibis.class(ibis-convert-methods-to-containers)))' %s | FileCheck %s
// CHECK-LABEL: ibis.class sym @ToContainers {
// CHECK: %[[VAL_0:.*]] = ibis.this <@foo::@ToContainers>
// CHECK: ibis.container sym @foo {
// CHECK: %[[VAL_1:.*]] = ibis.this <@foo::@foo>
// CHECK: %[[VAL_2:.*]] = ibis.port.input "arg0" sym @arg0 : !dc.value<i32>
// CHECK: %[[VAL_3:.*]] = ibis.port.read %[[VAL_2]] : !ibis.portref<in !dc.value<i32>>
// CHECK: %[[VAL_4:.*]] = ibis.port.output "out0" sym @out0 : !dc.value<i32>
// CHECK: ibis.port.write %[[VAL_4]], %[[VAL_5:.*]] : !ibis.portref<out !dc.value<i32>>
// CHECK: %[[VAL_6:.*]], %[[VAL_7:.*]] = dc.unpack %[[VAL_3]] : !dc.value<i32>
// CHECK: %[[VAL_8:.*]]:2 = dc.fork [2] %[[VAL_6]]
// CHECK: %[[VAL_9:.*]] = dc.pack %[[VAL_8]]#0, %[[VAL_7]] : i32
// CHECK: %[[VAL_10:.*]] = dc.pack %[[VAL_8]]#1, %[[VAL_7]] : i32
// CHECK: %[[VAL_5]] = ibis.sblock.dc (%[[VAL_11:.*]] : !dc.value<i32> = %[[VAL_9]], %[[VAL_12:.*]] : !dc.value<i32> = %[[VAL_10]]) -> !dc.value<i32> {
// CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_11]], %[[VAL_12]] : i32
// CHECK: ibis.sblock.return %[[VAL_13]] : i32
// CHECK: }
// CHECK: }
// CHECK: }
ibis.design @foo {
ibis.class sym @ToContainers {
%this = ibis.this <@foo::@ToContainers>
ibis.method.df @foo(%arg0: !dc.value<i32>) -> !dc.value<i32> {
%token, %output = dc.unpack %arg0 : !dc.value<i32>
%0:2 = dc.fork [2] %token
%1 = dc.pack %0#0, %output : i32
%2 = dc.pack %0#1, %output : i32
%3 = ibis.sblock.dc (%arg1 : !dc.value<i32> = %1, %arg2 : !dc.value<i32> = %2) -> !dc.value<i32> {
%4 = arith.addi %arg1, %arg2 : i32
ibis.sblock.return %4 : i32
}
ibis.return %3 : !dc.value<i32>
}
}
}

View File

@ -1,73 +0,0 @@
// The ultimate tunneling test - by having 3 intermediate levels for both up-
// and downwards tunneling, we are sure test all the possible combinations of
// tunneling. This is more of a sanity check that everything works as expected.
// RUN: circt-opt --split-input-file --ibis-tunneling \
// RUN: --ibis-lower-portrefs --ibis-clean-selfdrivers \
// RUN: --ibis-convert-containers-to-hw
ibis.design @foo {
ibis.container sym @D_up {
%this = ibis.this <@foo::@D_up>
%d = ibis.path [
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<child, @a_down : !ibis.scoperef> : !ibis.scoperef,
#ibis.step<child, @b : !ibis.scoperef> : !ibis.scoperef,
#ibis.step<child, @c : !ibis.scoperef> : !ibis.scoperef,
#ibis.step<child, @d : !ibis.scoperef<@D_down>> : !ibis.scoperef<@D_down>]
// Write an input port
%clk_ref = ibis.get_port %d, @clk_in : !ibis.scoperef<@D_down> -> !ibis.portref<in i1>
%clk = hw.constant 1 : i1
ibis.port.write %clk_ref, %clk : !ibis.portref<in i1>
// Read an input port
%clk_ref_2 = ibis.get_port %d, @clk_in : !ibis.scoperef<@D_down> -> !ibis.portref<out i1>
%clk_in_val = ibis.port.read %clk_ref_2 : !ibis.portref<out i1>
// Read an output port
%clk_out_ref = ibis.get_port %d, @clk_out : !ibis.scoperef<@D_down> -> !ibis.portref<out i1>
%clk_out_val = ibis.port.read %clk_out_ref : !ibis.portref<out i1>
}
ibis.container sym @C_up {
%this = ibis.this <@foo::@C_up>
%d = ibis.container.instance @d, @D_up
}
ibis.container sym @B_up {
%this = ibis.this <@foo::@B_up>
%c = ibis.container.instance @c, @C_up
}
ibis.container sym @A_up {
%this = ibis.this <@foo::@A_up>
%b = ibis.container.instance @b, @B_up
}
ibis.container sym @Top {
%this = ibis.this <@foo::@Top>
%a_down = ibis.container.instance @a_down, @A_down
%a_up = ibis.container.instance @a_up, @A_up
}
ibis.container sym @A_down {
%this = ibis.this <@foo::@A_down>
%b = ibis.container.instance @b, @B_down
}
ibis.container sym @B_down {
%this = ibis.this <@foo::@B_down>
%c = ibis.container.instance @c, @C_down
}
ibis.container sym @C_down {
%this = ibis.this <@foo::@C_down>
%d = ibis.container.instance @d, @D_down
}
ibis.container sym @D_down {
%this = ibis.this <@foo::@D_down>
%clk = ibis.port.input "clk_in" sym @clk_in : i1
%clk_out = ibis.port.output "clk_out" sym @clk_out : i1
%clk.val = ibis.port.read %clk : !ibis.portref<in i1>
ibis.port.write %clk_out, %clk.val : !ibis.portref<out i1>
}
}

View File

@ -1,260 +0,0 @@
// RUN: circt-opt --split-input-file --ibis-lower-portrefs %s | FileCheck %s
ibis.design @D {
ibis.container sym @C {
%this = ibis.this <@D::@C>
%in = ibis.port.input "in" sym @in : i1
%out = ibis.port.output "out" sym @out : i1
}
// CHECK-LABEL: ibis.container sym @AccessSibling {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@AccessSibling>
// CHECK: %[[VAL_1:.*]] = ibis.port.input "p_b_out" sym @p_b_out : i1
// CHECK: %[[VAL_2:.*]] = ibis.port.output "p_b_in" sym @p_b_in : i1
// CHECK: ibis.port.write %[[VAL_2]], %[[VAL_3:.*]] : !ibis.portref<out i1>
// CHECK: %[[VAL_3]] = ibis.port.read %[[VAL_1]] : !ibis.portref<in i1>
// CHECK: }
ibis.container sym @AccessSibling {
%this = ibis.this <@D::@AccessSibling>
%p_b_out = ibis.port.input "p_b_out" sym @p_b_out : !ibis.portref<out i1>
%p_b_out_val = ibis.port.read %p_b_out : !ibis.portref<in !ibis.portref<out i1>>
%p_b_in = ibis.port.input "p_b_in" sym @p_b_in : !ibis.portref<in i1>
%p_b_in_val = ibis.port.read %p_b_in : !ibis.portref<in !ibis.portref<in i1>>
// Loopback to ensure that value replacement is performed.
%v = ibis.port.read %p_b_out_val : !ibis.portref<out i1>
ibis.port.write %p_b_in_val, %v : !ibis.portref<in i1>
}
// CHECK-LABEL: ibis.container sym @Parent {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@Parent>
// CHECK: %[[VAL_1:.*]] = ibis.container.instance @a, <@D::@AccessSibling>
// CHECK: %[[VAL_2:.*]] = ibis.get_port %[[VAL_1]], @p_b_out : !ibis.scoperef<@D::@AccessSibling> -> !ibis.portref<in i1>
// CHECK: %[[VAL_3:.*]] = ibis.port.read %[[VAL_4:.*]] : !ibis.portref<out i1>
// CHECK: ibis.port.write %[[VAL_2]], %[[VAL_3]] : !ibis.portref<in i1>
// CHECK: %[[VAL_5:.*]] = ibis.get_port %[[VAL_1]], @p_b_in : !ibis.scoperef<@D::@AccessSibling> -> !ibis.portref<out i1>
// CHECK: %[[VAL_6:.*]] = ibis.port.read %[[VAL_5]] : !ibis.portref<out i1>
// CHECK: ibis.port.write %[[VAL_7:.*]], %[[VAL_6]] : !ibis.portref<in i1>
// CHECK: %[[VAL_8:.*]] = ibis.container.instance @b, <@D::@C>
// CHECK: %[[VAL_4]] = ibis.get_port %[[VAL_8]], @out : !ibis.scoperef<@D::@C> -> !ibis.portref<out i1>
// CHECK: %[[VAL_7]] = ibis.get_port %[[VAL_8]], @in : !ibis.scoperef<@D::@C> -> !ibis.portref<in i1>
// CHECK: }
ibis.container sym @Parent {
%this = ibis.this <@D::@Parent>
%a = ibis.container.instance @a, <@D::@AccessSibling>
%a.p_b_out = ibis.get_port %a, @p_b_out : !ibis.scoperef<@D::@AccessSibling> -> !ibis.portref<in !ibis.portref<out i1>>
ibis.port.write %a.p_b_out, %b.out : !ibis.portref<in !ibis.portref<out i1>>
%a.p_b_in = ibis.get_port %a, @p_b_in : !ibis.scoperef<@D::@AccessSibling> -> !ibis.portref<in !ibis.portref<in i1>>
ibis.port.write %a.p_b_in, %b.in : !ibis.portref<in !ibis.portref<in i1>>
%b = ibis.container.instance @b, <@D::@C>
%b.out = ibis.get_port %b, @out : !ibis.scoperef<@D::@C> -> !ibis.portref<out i1>
%b.in = ibis.get_port %b, @in : !ibis.scoperef<@D::@C> -> !ibis.portref<in i1>
}
}
// -----
ibis.design @D {
// CHECK-LABEL: ibis.container sym @ParentPortAccess {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@ParentPortAccess>
// CHECK: %[[VAL_1:.*]] = ibis.port.output "p_in" sym @p_in : i1
// CHECK: %[[VAL_2:.*]] = ibis.port.input "p_out" sym @p_out : i1
// CHECK: }
ibis.container sym @ParentPortAccess {
%this = ibis.this <@D::@ParentPortAccess>
%p_in = ibis.port.input "p_in" sym @p_in : !ibis.portref<in i1>
%p_in_val = ibis.port.read %p_in : !ibis.portref<in !ibis.portref<in i1>>
%p_out = ibis.port.input "p_out" sym @p_out : !ibis.portref<out i1>
%p_out_val = ibis.port.read %p_out : !ibis.portref<in !ibis.portref<out i1>>
}
// CHECK-LABEL: ibis.container sym @Parent {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@Parent>
// CHECK: %[[VAL_1:.*]] = ibis.container.instance @c, <@D::@ParentPortAccess>
// CHECK: %[[VAL_2:.*]] = ibis.get_port %[[VAL_1]], @p_in : !ibis.scoperef<@D::@ParentPortAccess> -> !ibis.portref<out i1>
// CHECK: %[[VAL_3:.*]] = ibis.port.read %[[VAL_2]] : !ibis.portref<out i1>
// CHECK: ibis.port.write %[[VAL_4:.*]], %[[VAL_3]] : !ibis.portref<in i1>
// CHECK: %[[VAL_5:.*]] = ibis.get_port %[[VAL_1]], @p_out : !ibis.scoperef<@D::@ParentPortAccess> -> !ibis.portref<in i1>
// CHECK: %[[VAL_6:.*]] = ibis.port.read %[[VAL_7:.*]] : !ibis.portref<out i1>
// CHECK: ibis.port.write %[[VAL_5]], %[[VAL_6]] : !ibis.portref<in i1>
// CHECK: %[[VAL_4]] = ibis.port.input "in" sym @in : i1
// CHECK: %[[VAL_7]] = ibis.port.output "out" sym @out : i1
// CHECK: }
ibis.container sym @Parent {
%this = ibis.this <@D::@Parent>
%c = ibis.container.instance @c, <@D::@ParentPortAccess>
%c.p_in = ibis.get_port %c, @p_in : !ibis.scoperef<@D::@ParentPortAccess> -> !ibis.portref<in !ibis.portref<in i1>>
ibis.port.write %c.p_in, %in : !ibis.portref<in !ibis.portref<in i1>>
%c.p_out = ibis.get_port %c, @p_out : !ibis.scoperef<@D::@ParentPortAccess> -> !ibis.portref<in !ibis.portref<out i1>>
ibis.port.write %c.p_out, %out : !ibis.portref<in !ibis.portref<out i1>>
%in = ibis.port.input "in" sym @in : i1
%out = ibis.port.output "out" sym @out : i1
}
}
// -----
ibis.design @D {
// C1 child -> P1 parent -> P2 parent -> C2 child -> C3 child
// CHECK-LABEL: ibis.container sym @C1 {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@C1>
// CHECK: %[[VAL_1:.*]] = ibis.port.output "parent_parent_c2_c3_in" sym @parent_parent_c2_c3_in : i1
// CHECK: ibis.port.write %[[VAL_1]], %[[VAL_2:.*]] : !ibis.portref<out i1>
// CHECK: %[[VAL_3:.*]] = ibis.port.input "parent_parent_c2_c3_out" sym @parent_parent_c2_c3_out : i1
// CHECK: %[[VAL_2]] = ibis.port.read %[[VAL_3]] : !ibis.portref<in i1>
// CHECK: }
ibis.container sym @C1 {
%this = ibis.this <@D::@C1>
%parent_parent_c2_c3_in = ibis.port.input "parent_parent_c2_c3_in" sym @parent_parent_c2_c3_in : !ibis.portref<in i1>
%parent_parent_c2_c3_out = ibis.port.input "parent_parent_c2_c3_out" sym @parent_parent_c2_c3_out : !ibis.portref<out i1>
// Assignment drivers - unwrap the ports and roundtrip read-write.
%parent_b_in_unwrapped = ibis.port.read %parent_parent_c2_c3_in : !ibis.portref<in !ibis.portref<in i1>>
%parent_b_out_unwrapped = ibis.port.read %parent_parent_c2_c3_out : !ibis.portref<in !ibis.portref<out i1>>
%parent_b_out_value = ibis.port.read %parent_b_out_unwrapped : !ibis.portref<out i1>
ibis.port.write %parent_b_in_unwrapped, %parent_b_out_value : !ibis.portref<in i1>
}
// CHECK-LABEL: ibis.container sym @C2 {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@C2>
// CHECK: %[[VAL_1:.*]] = ibis.container.instance @c3, <@D::@C>
// CHECK: %[[VAL_2:.*]] = ibis.get_port %[[VAL_1]], @in : !ibis.scoperef<@D::@C> -> !ibis.portref<in i1>
// CHECK: %[[VAL_3:.*]] = ibis.get_port %[[VAL_1]], @out : !ibis.scoperef<@D::@C> -> !ibis.portref<out i1>
// CHECK: %[[VAL_4:.*]] = ibis.port.input "parent_parent_c2_c3_in" sym @parent_parent_c2_c3_in : i1
// CHECK: %[[VAL_5:.*]] = ibis.port.read %[[VAL_4]] : !ibis.portref<in i1>
// CHECK: ibis.port.write %[[VAL_2]], %[[VAL_5]] : !ibis.portref<in i1>
// CHECK: %[[VAL_6:.*]] = ibis.port.output "parent_parent_c2_c3_out" sym @parent_parent_c2_c3_out : i1
// CHECK: %[[VAL_7:.*]] = ibis.port.read %[[VAL_3]] : !ibis.portref<out i1>
// CHECK: ibis.port.write %[[VAL_6]], %[[VAL_7]] : !ibis.portref<out i1>
// CHECK: }
ibis.container sym @C2 {
%this = ibis.this <@D::@C2>
%c3 = ibis.container.instance @c3, <@D::@C>
%c3.in = ibis.get_port %c3, @in : !ibis.scoperef<@D::@C> -> !ibis.portref<in i1>
%c3.out = ibis.get_port %c3, @out : !ibis.scoperef<@D::@C> -> !ibis.portref<out i1>
%parent_parent_c2_c3_in = ibis.port.output "parent_parent_c2_c3_in" sym @parent_parent_c2_c3_in : !ibis.portref<in i1>
%parent_parent_c2_c3_out = ibis.port.output "parent_parent_c2_c3_out" sym @parent_parent_c2_c3_out : !ibis.portref<out i1>
ibis.port.write %parent_parent_c2_c3_in, %c3.in : !ibis.portref<out !ibis.portref<in i1>>
ibis.port.write %parent_parent_c2_c3_out, %c3.out : !ibis.portref<out !ibis.portref<out i1>>
}
ibis.container sym @C {
%this = ibis.this <@D::@C>
%in = ibis.port.input "in" sym @in : i1
%out = ibis.port.output "out" sym @out : i1
}
// CHECK-LABEL: ibis.container sym @P1 {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@P1>
// CHECK: %[[VAL_1:.*]] = ibis.container.instance @c1, <@D::@C1>
// CHECK: %[[VAL_2:.*]] = ibis.get_port %[[VAL_1]], @parent_parent_c2_c3_in : !ibis.scoperef<@D::@C1> -> !ibis.portref<out i1>
// CHECK: %[[VAL_3:.*]] = ibis.port.read %[[VAL_2]] : !ibis.portref<out i1>
// CHECK: %[[VAL_4:.*]] = ibis.get_port %[[VAL_1]], @parent_parent_c2_c3_out : !ibis.scoperef<@D::@C1> -> !ibis.portref<in i1>
// CHECK: %[[VAL_5:.*]] = ibis.port.read %[[VAL_6:.*]] : !ibis.portref<in i1>
// CHECK: ibis.port.write %[[VAL_4]], %[[VAL_5]] : !ibis.portref<in i1>
// CHECK: %[[VAL_7:.*]] = ibis.port.output "parent_parent_c2_c3_in" sym @parent_parent_c2_c3_in : i1
// CHECK: ibis.port.write %[[VAL_7]], %[[VAL_3]] : !ibis.portref<out i1>
// CHECK: %[[VAL_6]] = ibis.port.input "parent_parent_c2_c3_out" sym @parent_parent_c2_c3_out : i1
// CHECK: }
ibis.container sym @P1 {
%this = ibis.this <@D::@P1>
%c1 = ibis.container.instance @c1, <@D::@C1>
%c1.parent_parent_c2_c3_in = ibis.get_port %c1, @parent_parent_c2_c3_in : !ibis.scoperef<@D::@C1> -> !ibis.portref<in !ibis.portref<in i1>>
ibis.port.write %c1.parent_parent_c2_c3_in, %0 : !ibis.portref<in !ibis.portref<in i1>>
%c1.parent_parent_c2_c3_out = ibis.get_port %c1, @parent_parent_c2_c3_out : !ibis.scoperef<@D::@C1> -> !ibis.portref<in !ibis.portref<out i1>>
ibis.port.write %c1.parent_parent_c2_c3_out, %1 : !ibis.portref<in !ibis.portref<out i1>>
%parent_parent_c2_c3_in = ibis.port.input "parent_parent_c2_c3_in" sym @parent_parent_c2_c3_in : !ibis.portref<in i1>
%0 = ibis.port.read %parent_parent_c2_c3_in : !ibis.portref<in !ibis.portref<in i1>>
%parent_parent_c2_c3_out = ibis.port.input "parent_parent_c2_c3_out" sym @parent_parent_c2_c3_out : !ibis.portref<out i1>
%1 = ibis.port.read %parent_parent_c2_c3_out : !ibis.portref<in !ibis.portref<out i1>>
}
// CHECK-LABEL: ibis.container sym @P2 {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@P2>
// CHECK: %[[VAL_1:.*]] = ibis.container.instance @p1, <@D::@P1>
// CHECK: %[[VAL_2:.*]] = ibis.get_port %[[VAL_1]], @parent_parent_c2_c3_in : !ibis.scoperef<@D::@P1> -> !ibis.portref<out i1>
// CHECK: %[[VAL_3:.*]] = ibis.port.read %[[VAL_2]] : !ibis.portref<out i1>
// CHECK: ibis.port.write %[[VAL_4:.*]], %[[VAL_3]] : !ibis.portref<in i1>
// CHECK: %[[VAL_5:.*]] = ibis.get_port %[[VAL_1]], @parent_parent_c2_c3_out : !ibis.scoperef<@D::@P1> -> !ibis.portref<in i1>
// CHECK: %[[VAL_6:.*]] = ibis.port.read %[[VAL_7:.*]] : !ibis.portref<out i1>
// CHECK: ibis.port.write %[[VAL_5]], %[[VAL_6]] : !ibis.portref<in i1>
// CHECK: %[[VAL_8:.*]] = ibis.container.instance @c2, <@D::@C2>
// CHECK: %[[VAL_7]] = ibis.get_port %[[VAL_8]], @parent_parent_c2_c3_out : !ibis.scoperef<@D::@C2> -> !ibis.portref<out i1>
// CHECK: %[[VAL_4]] = ibis.port.input "parent_parent_c2_c3_in_fw" sym @parent_parent_c2_c3_in_fw : i1
// CHECK: %[[VAL_9:.*]] = ibis.port.read %[[VAL_4]] : !ibis.portref<in i1>
// CHECK: %[[VAL_10:.*]] = ibis.get_port %[[VAL_8]], @parent_parent_c2_c3_in : !ibis.scoperef<@D::@C2> -> !ibis.portref<in i1>
// CHECK: ibis.port.write %[[VAL_10]], %[[VAL_9]] : !ibis.portref<in i1>
// CHECK: }
ibis.container sym @P2 {
%this = ibis.this <@D::@P2>
%p1 = ibis.container.instance @p1, <@D::@P1>
%p1.parent_parent_c2_c3_in = ibis.get_port %p1, @parent_parent_c2_c3_in : !ibis.scoperef<@D::@P1> -> !ibis.portref<in !ibis.portref<in i1>>
ibis.port.write %p1.parent_parent_c2_c3_in, %1 : !ibis.portref<in !ibis.portref<in i1>>
%p1.parent_parent_c2_c3_out = ibis.get_port %p1, @parent_parent_c2_c3_out : !ibis.scoperef<@D::@P1> -> !ibis.portref<in !ibis.portref<out i1>>
ibis.port.write %p1.parent_parent_c2_c3_out, %0 : !ibis.portref<in !ibis.portref<out i1>>
%c2 = ibis.container.instance @c2, <@D::@C2>
%c2.parent_parent_c2_c3_out = ibis.get_port %c2, @parent_parent_c2_c3_out : !ibis.scoperef<@D::@C2> -> !ibis.portref<out !ibis.portref<out i1>>
%0 = ibis.port.read %c2.parent_parent_c2_c3_out : !ibis.portref<out !ibis.portref<out i1>>
%c2.parent_parent_c2_c3_in = ibis.get_port %c2, @parent_parent_c2_c3_in : !ibis.scoperef<@D::@C2> -> !ibis.portref<out !ibis.portref<in i1>>
%1 = ibis.port.read %c2.parent_parent_c2_c3_in : !ibis.portref<out !ibis.portref<in i1>>
}
}
// -----
ibis.design @D {
// CHECK-LABEL: ibis.container sym @AccessParent {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@AccessParent>
// CHECK: %[[VAL_1:.*]] = ibis.port.output "p_out" sym @p_out : i1
// CHECK: %[[VAL_2:.*]] = ibis.port.input "p_in" sym @p_in : i1
// CHECK: }
ibis.container sym @AccessParent {
%this = ibis.this <@D::@AccessParent>
%p_out = ibis.port.input "p_out" sym @p_out : !ibis.portref<in i1>
%p_out.val = ibis.port.read %p_out : !ibis.portref<in !ibis.portref<in i1>>
%p_in = ibis.port.input "p_in" sym @p_in : !ibis.portref<out i1>
%p_in.val = ibis.port.read %p_in : !ibis.portref<in !ibis.portref<out i1>>
}
// CHECK-LABEL: ibis.container sym @Parent {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@Parent>
// CHECK: %[[VAL_1:.*]] = ibis.port.input "in" sym @in : i1
// CHECK: %[[VAL_2:.*]] = ibis.port.read %[[VAL_1]] : !ibis.portref<in i1>
// CHECK: %[[VAL_3:.*]] = ibis.wire.output @in.rd, %[[VAL_2]] : i1
// CHECK: %[[VAL_4:.*]] = ibis.port.output "out" sym @out : i1
// CHECK: %[[VAL_5:.*]], %[[VAL_6:.*]] = ibis.wire.input @out.wr : i1
// CHECK: ibis.port.write %[[VAL_4]], %[[VAL_6]] : !ibis.portref<out i1>
// CHECK: %[[VAL_7:.*]] = ibis.container.instance @c, <@D::@AccessParent>
// CHECK: %[[VAL_8:.*]] = ibis.get_port %[[VAL_7]], @p_out : !ibis.scoperef<@D::@AccessParent> -> !ibis.portref<out i1>
// CHECK: %[[VAL_9:.*]] = ibis.port.read %[[VAL_8]] : !ibis.portref<out i1>
// CHECK: ibis.port.write %[[VAL_5]], %[[VAL_9]] : !ibis.portref<in i1>
// CHECK: %[[VAL_10:.*]] = ibis.get_port %[[VAL_7]], @p_in : !ibis.scoperef<@D::@AccessParent> -> !ibis.portref<in i1>
// CHECK: %[[VAL_11:.*]] = ibis.port.read %[[VAL_3]] : !ibis.portref<out i1>
// CHECK: ibis.port.write %[[VAL_10]], %[[VAL_11]] : !ibis.portref<in i1>
// CHECK: }
ibis.container sym @Parent {
%this = ibis.this <@D::@Parent>
%in = ibis.port.input "in" sym @in : i1
%in.val = ibis.port.read %in : !ibis.portref<in i1>
%in.rd = ibis.wire.output @in.rd, %in.val : i1
%out = ibis.port.output "out" sym @out : i1
%out.wr, %out.wr.out = ibis.wire.input @out.wr : i1
ibis.port.write %out, %out.wr.out : !ibis.portref<out i1>
%c = ibis.container.instance @c, <@D::@AccessParent>
%c.p_out.ref = ibis.get_port %c, @p_out : !ibis.scoperef<@D::@AccessParent> -> !ibis.portref<in !ibis.portref<in i1>>
ibis.port.write %c.p_out.ref, %out.wr : !ibis.portref<in !ibis.portref<in i1>>
%c.p_in.ref = ibis.get_port %c, @p_in : !ibis.scoperef<@D::@AccessParent> -> !ibis.portref<in !ibis.portref<out i1>>
ibis.port.write %c.p_in.ref, %in.rd : !ibis.portref<in !ibis.portref<out i1>>
}
}

View File

@ -1,29 +0,0 @@
// RUN: circt-opt --pass-pipeline="builtin.module(ibis.design(ibis.class(ibis.method.df(ibis.sblock.isolated(ibis-prepare-scheduling)))))" \
// RUN: --allow-unregistered-dialect %s | FileCheck %s
// CHECK: ibis.method.df @foo(%[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32) -> (i32, i32) {
// CHECK: %[[VAL_3:.*]]:2 = ibis.sblock.isolated (%[[VAL_4:.*]] : i32 = %[[VAL_1]], %[[VAL_5:.*]] : i32 = %[[VAL_2]]) -> (i32, i32) {
// CHECK: %[[VAL_6:.*]], %[[VAL_7:.*]], %[[VAL_8:.*]], %[[VAL_9:.*]] = ibis.pipeline.header
// CHECK: %[[VAL_10:.*]], %[[VAL_11:.*]], %[[VAL_12:.*]] = pipeline.unscheduled(%[[VAL_13:.*]] : i32 = %[[VAL_4]], %[[VAL_14:.*]] : i32 = %[[VAL_5]]) stall(%[[VAL_9]]) clock(%[[VAL_6]]) reset(%[[VAL_7]]) go(%[[VAL_8]]) entryEn(%[[VAL_15:.*]]) {operator_lib = @ibis_operator_library} -> (out0 : i32, out1 : i32) {
// CHECK: %[[VAL_16:.*]] = "foo.op1"(%[[VAL_13]], %[[VAL_14]]) {ssp.operator_type = @foo.op1} : (i32, i32) -> i32
// CHECK: pipeline.return %[[VAL_16]], %[[VAL_13]] : i32, i32
// CHECK: }
// CHECK: ibis.sblock.return %[[VAL_17:.*]], %[[VAL_18:.*]] : i32, i32
// CHECK: }
ibis.design @foo {
ibis.class sym @PrepareScheduling {
%this = ibis.this <@foo::@PrepareScheduling>
// A test wherein the returned values are either a value generated by an
// operation in the pipeline, or a value that's passed through the pipeline.
// The resulting IR should have all values passing through the newly created
// pipeline.
ibis.method.df @foo(%a: i32, %b: i32) -> (i32, i32) {
%0, %1 = ibis.sblock.isolated (%arg0 : i32 = %a, %arg1 : i32 = %b) -> (i32, i32) {
%4 = "foo.op1"(%arg0, %arg1) : (i32, i32) -> i32
ibis.sblock.return %4, %arg0 : i32, i32
}
ibis.return %0, %1 : i32, i32
}
}
}

View File

@ -1,48 +0,0 @@
// RUN: circt-opt --pass-pipeline='builtin.module(ibis.design(ibis.class(ibis.method(ibis-reblock))))' %s | FileCheck %s
// CHECK-LABEL: ibis.class sym @Reblock {
// CHECK: %[[VAL_0:.*]] = ibis.this <@foo::@Reblock>
// CHECK: ibis.method @foo(%[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32) -> i32 {
// CHECK: %[[VAL_3:.*]] = ibis.sblock () -> i32 {
// CHECK: %[[VAL_4:.*]] = arith.addi %[[VAL_1]], %[[VAL_2]] : i32
// CHECK: ibis.sblock.return %[[VAL_4]] : i32
// CHECK: }
// CHECK: %[[VAL_5:.*]] = ibis.sblock () -> i32 attributes {maxThreads = 2 : i64} {
// CHECK: %[[VAL_6:.*]] = arith.addi %[[VAL_3]], %[[VAL_2]] : i32
// CHECK: %[[VAL_7:.*]] = arith.addi %[[VAL_6]], %[[VAL_2]] : i32
// CHECK: ibis.sblock.return %[[VAL_7]] : i32
// CHECK: }
// CHECK: %[[VAL_8:.*]] = ibis.sblock () -> i32 {
// CHECK: %[[VAL_9:.*]] = arith.addi %[[VAL_5]], %[[VAL_2]] : i32
// CHECK: ibis.sblock.return %[[VAL_9]] : i32
// CHECK: }
// CHECK: cf.br ^bb1(%[[VAL_8]] : i32)
// CHECK: ^bb1(%[[VAL_10:.*]]: i32):
// CHECK: %[[VAL_11:.*]] = ibis.sblock () -> i32 {
// CHECK: %[[VAL_12:.*]] = arith.addi %[[VAL_10]], %[[VAL_8]] : i32
// CHECK: ibis.sblock.return %[[VAL_12]] : i32
// CHECK: }
// CHECK: ibis.return %[[VAL_11]] : i32
// CHECK: }
// CHECK: }
ibis.design @foo {
ibis.class sym @Reblock {
%this = ibis.this <@foo::@Reblock>
ibis.method @foo(%arg0 : i32, %arg1 : i32) -> i32 {
%0 = arith.addi %arg0, %arg1 : i32
ibis.sblock.inline.begin {maxThreads = 2}
%inner = arith.addi %0, %arg1 : i32
%1 = arith.addi %inner, %arg1 : i32
ibis.sblock.inline.end
%2 = arith.addi %1, %arg1 : i32
// %0 is used within the same MLIR block but outside the scope.
cf.br ^bb1(%2 : i32)
^bb1(%barg : i32):
%3 = arith.addi %barg, %2 : i32
// %1 is used in a different MLIR block (dominated by the sblock parent block).
ibis.return %3 : i32
}
}
}

View File

@ -1,314 +0,0 @@
// RUN: circt-opt --split-input-file --ibis-tunneling %s | FileCheck %s
ibis.design @D {
ibis.container sym @C {
%this = ibis.this <@D::@C>
%in = ibis.port.input "in" sym @in : i1
%out = ibis.port.output "out" sym @out : i1
}
// CHECK-LABEL: ibis.container sym @AccessChild {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@AccessChild>
// CHECK: %[[VAL_1:.*]] = ibis.container.instance @c, <@D::@C>
// CHECK: %[[VAL_2:.*]] = ibis.get_port %[[VAL_1]], @out : !ibis.scoperef<@D::@C> -> !ibis.portref<out i1>
// CHECK: %[[VAL_3:.*]] = ibis.get_port %[[VAL_1]], @in : !ibis.scoperef<@D::@C> -> !ibis.portref<in i1>
// CHECK-NEXT: }
ibis.container sym @AccessChild {
%this = ibis.this <@D::@AccessChild>
%c = ibis.container.instance @c, <@D::@C>
%c_ref = ibis.path [
#ibis.step<child , @c : !ibis.scoperef<@D::@C>>
]
%c_in = ibis.get_port %c_ref, @in : !ibis.scoperef<@D::@C> -> !ibis.portref<in i1>
%c_out = ibis.get_port %c_ref, @out : !ibis.scoperef<@D::@C> -> !ibis.portref<out i1>
}
}
// -----
// CHECK-LABEL: // -----
ibis.design @D {
ibis.container sym @C {
%this = ibis.this <@D::@C>
%in = ibis.port.input "in" sym @in : i1
%out = ibis.port.output "out" sym @out : i1
}
// CHECK-LABEL: ibis.container sym @AccessSibling {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@AccessSibling>
// CHECK: %[[VAL_1:.*]] = ibis.port.input "[[VAL_1]]" sym @[[VAL_1]] : !ibis.portref<out i1>
// CHECK: %[[VAL_2:.*]] = ibis.port.read %[[VAL_1]] : !ibis.portref<in !ibis.portref<out i1>>
// CHECK: %[[VAL_3:.*]] = ibis.port.input "[[VAL_3]]" sym @[[VAL_3]] : !ibis.portref<in i1>
// CHECK: %[[VAL_4:.*]] = ibis.port.read %[[VAL_3]] : !ibis.portref<in !ibis.portref<in i1>>
// CHECK: }
ibis.container sym @AccessSibling {
%this = ibis.this <@D::@AccessSibling>
%sibling = ibis.path [
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<child , @b : !ibis.scoperef<@D::@C>>
]
%c_in = ibis.get_port %sibling, @in : !ibis.scoperef<@D::@C> -> !ibis.portref<in i1>
%c_out = ibis.get_port %sibling, @out : !ibis.scoperef<@D::@C> -> !ibis.portref<out i1>
}
// CHECK-LABEL: ibis.container sym @Parent {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@Parent>
// CHECK: %[[VAL_1:.*]] = ibis.container.instance @a, <@D::@AccessSibling>
// CHECK: %[[VAL_2:.*]] = ibis.get_port %[[VAL_1]], @p_b_out.rd : !ibis.scoperef<@D::@AccessSibling> -> !ibis.portref<in !ibis.portref<out i1>>
// CHECK: ibis.port.write %[[VAL_2]], %[[VAL_3:.*]] : !ibis.portref<in !ibis.portref<out i1>>
// CHECK: %[[VAL_4:.*]] = ibis.get_port %[[VAL_1]], @p_b_in.wr : !ibis.scoperef<@D::@AccessSibling> -> !ibis.portref<in !ibis.portref<in i1>>
// CHECK: ibis.port.write %[[VAL_4]], %[[VAL_5:.*]] : !ibis.portref<in !ibis.portref<in i1>>
// CHECK: %[[VAL_6:.*]] = ibis.container.instance @b, <@D::@C>
// CHECK: %[[VAL_3]] = ibis.get_port %[[VAL_6]], @out : !ibis.scoperef<@D::@C> -> !ibis.portref<out i1>
// CHECK: %[[VAL_5]] = ibis.get_port %[[VAL_6]], @in : !ibis.scoperef<@D::@C> -> !ibis.portref<in i1>
// CHECK: }
ibis.container sym @Parent {
%this = ibis.this <@D::@Parent>
%a = ibis.container.instance @a, <@D::@AccessSibling>
%b = ibis.container.instance @b, <@D::@C>
}
}
// -----
// CHECK-LABEL: // -----
// "Full"/recursive case.
// C1 child -> P1 parent -> P2 parent -> C2 child -> C3 child
ibis.design @D {
// CHECK-LABEL: ibis.container sym @C1 {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@C1>
// CHECK: %[[VAL_1:.*]] = ibis.port.input "p_p_c2_c3_out.rd" sym @p_p_c2_c3_out.rd : !ibis.portref<out i1>
// CHECK: %[[VAL_2:.*]] = ibis.port.read %[[VAL_1]] : !ibis.portref<in !ibis.portref<out i1>>
// CHECK: %[[VAL_3:.*]] = ibis.port.input "p_p_c2_c3_in.wr" sym @p_p_c2_c3_in.wr : !ibis.portref<in i1>
// CHECK: %[[VAL_4:.*]] = ibis.port.read %[[VAL_3]] : !ibis.portref<in !ibis.portref<in i1>>
// CHECK: }
ibis.container sym @C1 {
%this = ibis.this <@D::@C1>
%c3 = ibis.path [
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<child , @c2 : !ibis.scoperef>,
#ibis.step<child , @c3 : !ibis.scoperef<@D::@C>>
]
%c_in = ibis.get_port %c3, @in : !ibis.scoperef<@D::@C> -> !ibis.portref<in i1>
%c_out = ibis.get_port %c3, @out : !ibis.scoperef<@D::@C> -> !ibis.portref<out i1>
}
// CHECK-LABEL: ibis.container sym @C2 {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@C2>
// CHECK: %[[VAL_1:.*]] = ibis.container.instance @c3, <@D::@C>
// CHECK: %[[VAL_2:.*]] = ibis.get_port %[[VAL_1]], @out : !ibis.scoperef<@D::@C> -> !ibis.portref<out i1>
// CHECK: %[[VAL_3:.*]] = ibis.get_port %[[VAL_1]], @in : !ibis.scoperef<@D::@C> -> !ibis.portref<in i1>
// CHECK: %[[VAL_4:.*]] = ibis.port.output "p_p_c2_c3_out.rd" sym @p_p_c2_c3_out.rd : !ibis.portref<out i1>
// CHECK: %[[VAL_5:.*]] = ibis.port.output "p_p_c2_c3_in.wr" sym @p_p_c2_c3_in.wr : !ibis.portref<in i1>
// CHECK: ibis.port.write %[[VAL_4]], %[[VAL_2]] : !ibis.portref<out !ibis.portref<out i1>>
// CHECK: ibis.port.write %[[VAL_5]], %[[VAL_3]] : !ibis.portref<out !ibis.portref<in i1>>
// CHECK: }
ibis.container sym @C2 {
%this = ibis.this <@D::@C2>
%c3 = ibis.container.instance @c3, <@D::@C>
}
ibis.container sym @C {
%this = ibis.this <@D::@C>
%in = ibis.port.input "in" sym @in : i1
%out = ibis.port.output "out" sym @out : i1
}
// CHECK-LABEL: ibis.container sym @P1 {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@P1>
// CHECK: %[[VAL_1:.*]] = ibis.container.instance @c1, <@D::@C1>
// CHECK: %[[VAL_2:.*]] = ibis.get_port %[[VAL_1]], @p_p_c2_c3_out.rd : !ibis.scoperef<@D::@C1> -> !ibis.portref<in !ibis.portref<out i1>>
// CHECK: ibis.port.write %[[VAL_2]], %[[VAL_3:.*]] : !ibis.portref<in !ibis.portref<out i1>>
// CHECK: %[[VAL_4:.*]] = ibis.get_port %[[VAL_1]], @p_p_c2_c3_in.wr : !ibis.scoperef<@D::@C1> -> !ibis.portref<in !ibis.portref<in i1>>
// CHECK: ibis.port.write %[[VAL_4]], %[[VAL_5:.*]] : !ibis.portref<in !ibis.portref<in i1>>
// CHECK: %[[VAL_6:.*]] = ibis.port.input "p_p_c2_c3_out.rd" sym @p_p_c2_c3_out.rd : !ibis.portref<out i1>
// CHECK: %[[VAL_3]] = ibis.port.read %[[VAL_6]] : !ibis.portref<in !ibis.portref<out i1>>
// CHECK: %[[VAL_7:.*]] = ibis.port.input "p_p_c2_c3_in.wr" sym @p_p_c2_c3_in.wr : !ibis.portref<in i1>
// CHECK: %[[VAL_5]] = ibis.port.read %[[VAL_7]] : !ibis.portref<in !ibis.portref<in i1>>
// CHECK: }
ibis.container sym @P1 {
%this = ibis.this <@D::@P1>
%c1 = ibis.container.instance @c1, <@D::@C1>
}
// CHECK-LABEL: ibis.container sym @P2 {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@P2>
// CHECK: %[[VAL_1:.*]] = ibis.container.instance @p1, <@D::@P1>
// CHECK: %[[VAL_2:.*]] = ibis.get_port %[[VAL_1]], @p_p_c2_c3_out.rd : !ibis.scoperef<@D::@P1> -> !ibis.portref<in !ibis.portref<out i1>>
// CHECK: ibis.port.write %[[VAL_2]], %[[VAL_3:.*]] : !ibis.portref<in !ibis.portref<out i1>>
// CHECK: %[[VAL_4:.*]] = ibis.get_port %[[VAL_1]], @p_p_c2_c3_in.wr : !ibis.scoperef<@D::@P1> -> !ibis.portref<in !ibis.portref<in i1>>
// CHECK: ibis.port.write %[[VAL_4]], %[[VAL_5:.*]] : !ibis.portref<in !ibis.portref<in i1>>
// CHECK: %[[VAL_6:.*]] = ibis.container.instance @c2, <@D::@C2>
// CHECK: %[[VAL_7:.*]] = ibis.get_port %[[VAL_6]], @p_p_c2_c3_in.wr : !ibis.scoperef<@D::@C2> -> !ibis.portref<out !ibis.portref<in i1>>
// CHECK: %[[VAL_5]] = ibis.port.read %[[VAL_7]] : !ibis.portref<out !ibis.portref<in i1>>
// CHECK: %[[VAL_8:.*]] = ibis.get_port %[[VAL_6]], @p_p_c2_c3_out.rd : !ibis.scoperef<@D::@C2> -> !ibis.portref<out !ibis.portref<out i1>>
// CHECK: %[[VAL_3]] = ibis.port.read %[[VAL_8]] : !ibis.portref<out !ibis.portref<out i1>>
// CHECK: }
ibis.container sym @P2 {
%this = ibis.this <@D::@P2>
%p1 = ibis.container.instance @p1, <@D::@P1>
%c2 = ibis.container.instance @c2, <@D::@C2>
}
}
// -----
// CHECK-LABEL: // -----
ibis.design @D {
// CHECK-LABEL: ibis.container sym @AccessParent {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@AccessParent>
// CHECK: %[[VAL_1:.*]] = ibis.port.input "p_out.wr" sym @p_out.wr : !ibis.portref<in i1>
// CHECK: %[[VAL_2:.*]] = ibis.port.read %[[VAL_1]] : !ibis.portref<in !ibis.portref<in i1>>
// CHECK: %[[VAL_3:.*]] = ibis.port.input "p_in.rd" sym @p_in.rd : !ibis.portref<out i1>
// CHECK: %[[VAL_4:.*]] = ibis.port.read %[[VAL_3]] : !ibis.portref<in !ibis.portref<out i1>>
// CHECK: }
ibis.container sym @AccessParent {
%this = ibis.this <@D::@AccessParent>
%p = ibis.path [
#ibis.step<parent : !ibis.scoperef<@D::@Parent>>
]
// get_port states the intended usage of the port. Hence we should be able to
// request a parent input port as an output port (readable), and vice versa.
// This will insert wires in the target container to facilitate the direction
// flip.
%p_in_ref = ibis.get_port %p, @in : !ibis.scoperef<@D::@Parent> -> !ibis.portref<out i1>
%p_out_ref = ibis.get_port %p, @out : !ibis.scoperef<@D::@Parent> -> !ibis.portref<in i1>
}
// CHECK-LABEL: ibis.container sym @Parent {
// CHECK: %[[VAL_0:.*]] = ibis.this <@D::@Parent>
// CHECK: %[[VAL_1:.*]] = ibis.port.input "in" sym @in : i1
// CHECK: %[[VAL_2:.*]] = ibis.port.read %[[VAL_1]] : !ibis.portref<in i1>
// CHECK: %[[VAL_3:.*]] = ibis.wire.output @in.rd, %[[VAL_2]] : i1
// CHECK: %[[VAL_4:.*]] = ibis.port.output "out" sym @out : i1
// CHECK: %[[VAL_5:.*]], %[[VAL_6:.*]] = ibis.wire.input @out.wr : i1
// CHECK: ibis.port.write %[[VAL_4]], %[[VAL_6]] : !ibis.portref<out i1>
// CHECK: %[[VAL_7:.*]] = ibis.container.instance @c, <@D::@AccessParent>
// CHECK: %[[VAL_8:.*]] = ibis.get_port %[[VAL_7]], @p_out.wr : !ibis.scoperef<@D::@AccessParent> -> !ibis.portref<in !ibis.portref<in i1>>
// CHECK: ibis.port.write %[[VAL_8]], %[[VAL_5]] : !ibis.portref<in !ibis.portref<in i1>>
// CHECK: %[[VAL_9:.*]] = ibis.get_port %[[VAL_7]], @p_in.rd : !ibis.scoperef<@D::@AccessParent> -> !ibis.portref<in !ibis.portref<out i1>>
// CHECK: ibis.port.write %[[VAL_9]], %[[VAL_3]] : !ibis.portref<in !ibis.portref<out i1>>
// CHECK: }
ibis.container sym @Parent {
%this = ibis.this <@D::@Parent>
%in = ibis.port.input "in" sym @in : i1
%out = ibis.port.output "out" sym @out : i1
%c = ibis.container.instance @c, <@D::@AccessParent>
}
}
// -----
// CHECK-LABEL: // -----
ibis.design @D {
ibis.container sym @C {
%this = ibis.this <@D::@C>
%in = ibis.port.input "in" sym @in : i1
%out = ibis.port.output "out" sym @out : i1
}
// TODO: support this case. Too hard to support now. Problem is that hw.module
// cannot live within an ibis.design, but we need to run this pass on the
// ibis.design op. I don't think it's critical that we support this case currently.
// COM: CHECK-LABEL: hw.module @AccessChildFromHW() {
// COM: CHECK: %[[VAL_0:.*]] = ibis.container.instance @c, <@D::@C>
// COM: CHECK: %[[VAL_1:.*]] = ibis.get_port %[[VAL_0]], @out : !ibis.scoperef<@D::@C> -> !ibis.portref<out i1>
// COM: CHECK: %[[VAL_2:.*]] = ibis.get_port %[[VAL_0]], @in : !ibis.scoperef<@D::@C> -> !ibis.portref<in i1>
// COM: CHECK: hw.output
// COM: CHECK: }
}
hw.module @AccessChildFromHW() {
%c = ibis.container.instance @c, <@D::@C>
%c_ref = ibis.path [
#ibis.step<child , @c : !ibis.scoperef<@D::@C>>
]
%c_in = ibis.get_port %c_ref, @in : !ibis.scoperef<@D::@C> -> !ibis.portref<in i1>
%c_out = ibis.get_port %c_ref, @out : !ibis.scoperef<@D::@C> -> !ibis.portref<out i1>
}
// -----
// CHECK-LABEL: // -----
ibis.design @D {
// The ultimate tunneling test - by having 3 intermediate levels for both up-
// and downwards tunneling, we are sure test all the possible combinations of
// tunneling.
ibis.container sym @D_up {
%this = ibis.this <@D::@D_up>
%d = ibis.path [
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<child, @a_down : !ibis.scoperef> : !ibis.scoperef,
#ibis.step<child, @b : !ibis.scoperef> : !ibis.scoperef,
#ibis.step<child, @c : !ibis.scoperef> : !ibis.scoperef,
#ibis.step<child, @d : !ibis.scoperef<@D::@D_down>> : !ibis.scoperef<@D::@D_down>]
// Write an input port
%clk_ref = ibis.get_port %d, @clk_in : !ibis.scoperef<@D::@D_down> -> !ibis.portref<in i1>
%clk = hw.constant 1 : i1
ibis.port.write %clk_ref, %clk : !ibis.portref<in i1>
// Read an input port
%clk_ref_2 = ibis.get_port %d, @clk_in : !ibis.scoperef<@D::@D_down> -> !ibis.portref<out i1>
%clk_in_val = ibis.port.read %clk_ref_2 : !ibis.portref<out i1>
// Read an output port
%clk_out_ref = ibis.get_port %d, @clk_out : !ibis.scoperef<@D::@D_down> -> !ibis.portref<out i1>
%clk_out_val = ibis.port.read %clk_out_ref : !ibis.portref<out i1>
}
ibis.container sym @C_up {
%this = ibis.this <@D::@C_up>
%d = ibis.container.instance @d, <@D::@D_up>
}
ibis.container sym @B_up {
%this = ibis.this <@D::@B_up>
%c = ibis.container.instance @c, <@D::@C_up>
}
ibis.container sym @A_up {
%this = ibis.this <@D::@A_up>
%b = ibis.container.instance @b, <@D::@B_up>
}
ibis.container sym @Top {
%this = ibis.this <@D::@Top>
%a_down = ibis.container.instance @a_down, <@D::@A_down>
%a_up = ibis.container.instance @a_up, <@D::@A_up>
}
ibis.container sym @A_down {
%this = ibis.this <@D::@A_down>
%b = ibis.container.instance @b, <@D::@B_down>
}
ibis.container sym @B_down {
%this = ibis.this <@D::@B_down>
%c = ibis.container.instance @c, <@D::@C_down>
}
ibis.container sym @C_down {
%this = ibis.this <@D::@C_down>
%d = ibis.container.instance @d, <@D::@D_down>
}
ibis.container sym @D_down {
%this = ibis.this <@D::@D_down>
%clk = ibis.port.input "clk_in" sym @clk_in : i1
%clk_out = ibis.port.output "clk_out" sym @clk_out : i1
%clk.val = ibis.port.read %clk : !ibis.portref<in i1>
ibis.port.write %clk_out, %clk.val : !ibis.portref<out i1>
}
}

View File

@ -1,64 +0,0 @@
// RUN: circt-opt %s | circt-opt | FileCheck %s
// RUN: circt-opt %s --ibis-call-prep | circt-opt | FileCheck %s --check-prefix=PREP
// CHECK-LABEL: ibis.class sym @C {
// CHECK: ibis.method @getAndSet(%x: ui32) -> ui32 {
// CHECK: ibis.return %x : ui32
// CHECK: ibis.method @returnNothingWithRet() -> () {
// CHECK: ibis.return
// PREP-LABEL: ibis.class sym @C {
// PREP: ibis.method @getAndSet(%arg: !hw.struct<x: ui32>) -> ui32 {
// PREP: %x = hw.struct_explode %arg : !hw.struct<x: ui32>
// PREP: ibis.return %x : ui32
// PREP: ibis.method @returnNothingWithRet(%arg: !hw.struct<>) -> () {
// PREP: hw.struct_explode %arg : !hw.struct<>
// PREP: ibis.return
ibis.design @foo {
ibis.class sym @C {
%this = ibis.this <@foo::@C>
ibis.method @getAndSet(%x: ui32) -> ui32 {
ibis.return %x : ui32
}
ibis.method @returnNothingWithRet() {
ibis.return
}
}
// CHECK-LABEL: ibis.class sym @User {
// CHECK: [[c:%.+]] = ibis.instance @c, <@foo::@C>
// CHECK: ibis.method @getAndSetWrapper(%new_value: ui32) -> ui32 {
// CHECK: [[x:%.+]] = ibis.call <@foo::@getAndSet>(%new_value) : (ui32) -> ui32
// CHECK: ibis.return [[x]] : ui32
// CHECK: ibis.method @getAndSetDup(%new_value: ui32) -> ui32 {
// CHECK: [[x:%.+]] = ibis.call <@foo::@getAndSet>(%new_value) : (ui32) -> ui32
// CHECK: ibis.return [[x]] : ui32
// PREP-LABEL: ibis.class sym @User {
// PREP: [[c:%.+]] = ibis.instance @c, <@foo::@C>
// PREP: ibis.method @getAndSetWrapper(%arg: !hw.struct<new_value: ui32>) -> ui32 {
// PREP: %new_value = hw.struct_explode %arg : !hw.struct<new_value: ui32>
// PREP: [[STRUCT1:%.+]] = hw.struct_create (%new_value) {sv.namehint = "getAndSet_args_called_from_getAndSetWrapper"} : !hw.struct<x: ui32>
// PREP: [[CALLRES1:%.+]] = ibis.call <@foo::@getAndSet>([[STRUCT1]]) : (!hw.struct<x: ui32>) -> ui32
// PREP: ibis.method @getAndSetDup(%arg: !hw.struct<new_value: ui32>) -> ui32 {
// PREP: %new_value = hw.struct_explode %arg : !hw.struct<new_value: ui32>
// PREP: [[STRUCT2:%.+]] = hw.struct_create (%new_value) {sv.namehint = "getAndSet_args_called_from_getAndSetDup"} : !hw.struct<x: ui32>
// PREP: [[CALLRES2:%.+]] = ibis.call <@foo::@getAndSet>([[STRUCT2]]) : (!hw.struct<x: ui32>) -> ui32
// PREP: ibis.return [[CALLRES2]] : ui32
ibis.class sym @User {
%this = ibis.this <@foo::@User>
ibis.instance @c, <@foo::@C>
ibis.method @getAndSetWrapper(%new_value: ui32) -> ui32 {
%x = ibis.call <@foo::@getAndSet>(%new_value): (ui32) -> ui32
ibis.return %x : ui32
}
ibis.method @getAndSetDup(%new_value: ui32) -> ui32 {
%x = ibis.call <@foo::@getAndSet>(%new_value): (ui32) -> ui32
ibis.return %x : ui32
}
}
}

View File

@ -1,43 +0,0 @@
// RUN: circt-opt --split-input-file --allow-unregistered-dialect --ibis-tunneling --verify-diagnostics %s
ibis.design @foo {
ibis.container sym @Parent {
%this = ibis.this <@foo::@Parent>
%in = ibis.port.input "in" sym @in : i1
}
ibis.container sym @Orphan {
%this = ibis.this <@foo::@Orphan>
// expected-error @+2 {{'ibis.path' op cannot tunnel up from "Orphan" because it has no uses}}
// expected-error @+1 {{failed to legalize operation 'ibis.path' that was explicitly marked illegal}}
%parent = ibis.path [
#ibis.step<parent : !ibis.scoperef<@foo::@Parent>>
]
%p = ibis.get_port %parent, @in : !ibis.scoperef<@foo::@Parent> -> !ibis.portref<in i1>
}
}
// -----
ibis.design @foo {
ibis.container sym @Parent {
%this = ibis.this <@foo::@Parent>
%mc = ibis.container.instance @mc, <@foo::@MissingChild>
}
ibis.container sym @Child {
%this = ibis.this <@foo::@Child>
%in = ibis.port.input "in" sym @in : i1
}
ibis.container sym @MissingChild {
%this = ibis.this <@foo::@MissingChild>
// expected-error @+2 {{'ibis.path' op expected an instance named @c in @Parent but found none}}
// expected-error @+1 {{failed to legalize operation 'ibis.path' that was explicitly marked illegal}}
%parent = ibis.path [
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<child , @c : !ibis.scoperef<@foo::@Child>>
]
%p = ibis.get_port %parent, @in : !ibis.scoperef<@foo::@Child> -> !ibis.portref<in i1>
}
}

View File

@ -1,40 +0,0 @@
// RUN: circt-opt --allow-unregistered-dialect --split-input-file --canonicalize --cse %s | FileCheck %s
ibis.design @foo {
// CHECK-LABEL: ibis.container sym @GetPortOnThis {
// CHECK: %[[VAL_0:.*]] = ibis.this <@foo::@GetPortOnThis>
// CHECK: %[[VAL_1:.*]] = ibis.port.input "in" sym @in : i1
// CHECK: "foo.user"(%[[VAL_1]]) : (!ibis.portref<in i1>) -> ()
// CHECK: }
ibis.container sym @GetPortOnThis {
%this = ibis.this <@foo::@GetPortOnThis>
%p = ibis.port.input "in" sym @in : i1
%p2 = ibis.get_port %this, @in : !ibis.scoperef<@foo::@GetPortOnThis> -> !ibis.portref<in i1>
"foo.user"(%p2) : (!ibis.portref<in i1>) -> ()
}
}
// -----
ibis.design @foo {
ibis.container sym @C {
%this = ibis.this <@foo::@C>
}
// CHECK-LABEL: ibis.container sym @AccessChild {
// CHECK: %[[VAL_0:.*]] = ibis.this <@foo::@AccessChild>
// CHECK: %[[VAL_1:.*]] = ibis.container.instance @c, <@foo::@C
// CHECK: "foo.user"(%[[VAL_1]]) : (!ibis.scoperef<@foo::@C>) -> ()
// CHECK: }
ibis.container sym @AccessChild {
%this = ibis.this <@foo::@AccessChild>
%c = ibis.container.instance @c, <@foo::@C>
%c_ref = ibis.path [
#ibis.step<child , @c : !ibis.scoperef<@foo::@C>>
]
"foo.user"(%c_ref) : (!ibis.scoperef<@foo::@C>) -> ()
}
}

View File

@ -1,96 +0,0 @@
// RUN: circt-opt --split-input-file --verify-diagnostics %s
ibis.design @foo {
ibis.class sym @C {
%this = ibis.this <@foo::@C>
ibis.method @typeMismatch1() -> (ui32, i32) {
// expected-error @+1 {{'ibis.return' op must have the same number of operands as the method has results}}
ibis.return
}
}
}
// -----
ibis.design @foo {
ibis.class sym @C {
%this = ibis.this <@foo::@C>
ibis.method @typeMismatch3() -> ui32 {
%c = hw.constant 1 : i8
// expected-error @+1 {{'ibis.return' op operand type ('i8') must match function return type ('ui32')}}
ibis.return %c : i8
}
}
}
// -----
ibis.design @foo {
// expected-error @+1 {{'ibis.class' op must contain only one 'ibis.this' operation}}
ibis.class sym @MultipleThis {
%this = ibis.this <@foo::@MultipleThis>
%this2 = ibis.this <@foo::@MultipleThis>
}
}
// -----
ibis.design @foo {
// expected-error @+1 {{'ibis.container' op must contain a 'ibis.this' operation}}
ibis.container sym @NoThis {
}
}
// -----
ibis.design @foo {
ibis.class sym @PathStepParentWithInstanceName {
%this = ibis.this <@foo::@PathStepParentWithInstanceName>
// expected-error @+1 {{ibis.step 'parent' may not specify an instance name}}
%p = ibis.path [#ibis.step<parent , @a : !ibis.scoperef>]
}
}
// -----
ibis.design @foo {
ibis.class sym @PathStepInvalidType {
%this = ibis.this <@foo::@PathStepParentWithInstanceName>
// expected-error @+1 {{ibis.step type must be an !ibis.scoperef type}}
%p = ibis.path [#ibis.step<parent : i1>]
}
}
// -----
ibis.design @foo {
ibis.class sym @PathStepChildMissingSymbol {
%this = ibis.this <@foo::@PathStepNonExistingChild>
// expected-error @+1 {{ibis.step 'child' must specify an instance name}}
%p = ibis.path [#ibis.step<child : !ibis.scoperef<@foo::@A>>]
}
}
// -----
ibis.design @foo {
ibis.class sym @InvalidVar {
%this = ibis.this <@foo::@C>
// expected-error @+1 {{'ibis.var' op attribute 'type' failed to satisfy constraint: any memref type}}
ibis.var @var : i32
}
}
// -----
ibis.design @foo {
ibis.class sym @InvalidReturn {
%this = ibis.this <@foo::@InvalidReturn>
ibis.method @foo() {
%c = hw.constant 1 : i32
// expected-error @+1 {{'ibis.sblock.return' op number of operands must match number of block outputs}}
%ret = ibis.sblock() -> i32 {
}
ibis.return
}
}
}

View File

@ -1,74 +0,0 @@
// RUN: circt-opt --hw-verify-irn --split-input-file --verify-diagnostics %s
ibis.design @foo {
ibis.class sym @MissingPort {
%this = ibis.this <@foo::@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<@foo::@MissingPort> -> !ibis.portref<in i1>
}
}
// -----
ibis.design @foo {
ibis.class sym @InvalidGetVar2 {
%this = ibis.this <@foo::@InvalidGetVar2>
ibis.var @var : memref<i32>
ibis.method @foo() {
%parent = ibis.path [
#ibis.step<parent : !ibis.scoperef<@foo::@InvalidGetVar2>>
]
// expected-error @+1 {{'ibis.get_var' op dereferenced type ('memref<i1>') must match variable type ('memref<i32>')}}
%var = ibis.get_var %parent, @var : !ibis.scoperef<@foo::@InvalidGetVar2> -> memref<i1>
ibis.return
}
}
}
// -----
ibis.design @foo {
ibis.class sym @InvalidGetVar {
%this = ibis.this <@foo::@InvalidGetVar>
ibis.var @var : memref<i32>
ibis.method @foo() {
%parent = ibis.path [
#ibis.step<parent : !ibis.scoperef<@foo::@InvalidGetVar>>
]
// expected-error @+1 {{'ibis.get_var' op result #0 must be memref of any type values, but got 'i32'}}
%var = ibis.get_var %parent, @var : !ibis.scoperef<@foo::@InvalidGetVar> -> i32
ibis.return
}
}
}
// -----
ibis.design @foo {
ibis.class sym @PortTypeMismatch {
%this = ibis.this <@foo::@PortTypeMismatch>
ibis.port.input "in" sym @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<@foo::@PortTypeMismatch> -> !ibis.portref<in i2>
}
}
// -----
ibis.design @foo {
ibis.class sym @PathStepNonExistingChild {
%this = ibis.this <@foo::@PathStepNonExistingChild>
// expected-error @+1 {{'ibis.path' op ibis.step scoperef symbol '@A' does not exist}}
%p = ibis.path [#ibis.step<child , @a : !ibis.scoperef<@foo::@A>>]
}
}
// -----
ibis.design @foo {
ibis.class sym @PathStepNonExistingParent {
%this = ibis.this <@foo::@PathStepNonExistingParent>
// expected-error @+1 {{'ibis.path' op last ibis.step in path must specify a symbol for the scoperef}}
%p = ibis.path [#ibis.step<parent : !ibis.scoperef>]
}
}

View File

@ -1,145 +0,0 @@
// RUN: circt-opt %s | circt-opt | FileCheck %s
ibis.design @foo {
// CHECK-LABEL: ibis.class sym @HighLevel {
// CHECK-NEXT: %this = ibis.this <@foo::@HighLevel>
// CHECK-NEXT: ibis.var @single : memref<i32>
// CHECK-NEXT: ibis.var @array : memref<10xi32>
// CHECK-NEXT: ibis.method @foo() -> (i32, i32) {
// CHECK-NEXT: %parent = ibis.path [#ibis.step<parent : !ibis.scoperef<@foo::@HighLevel>> : !ibis.scoperef<@foo::@HighLevel>]
// CHECK-NEXT: %single = ibis.get_var %parent, @single : !ibis.scoperef<@foo::@HighLevel> -> memref<i32>
// CHECK-NEXT: %array = ibis.get_var %parent, @array : !ibis.scoperef<@foo::@HighLevel> -> memref<10xi32>
// CHECK-NEXT: %alloca = memref.alloca() : memref<i32>
// CHECK-NEXT: %c32_i32 = hw.constant 32 : i32
// CHECK-NEXT: %0:2 = ibis.sblock (%arg0 : i32 = %c32_i32) -> (i32, i32) attributes {schedule = 1 : i64} {
// CHECK-NEXT: %1 = memref.load %alloca[] : memref<i32>
// CHECK-NEXT: memref.store %arg0, %alloca[] : memref<i32>
// CHECK-NEXT: ibis.sblock.return %1, %1 : i32, i32
// CHECK-NEXT: }
// CHECK-NEXT: ibis.return %0#0, %0#1 : i32, i32
// CHECK-NEXT: }
// CHECK-NEXT: ibis.method.df @bar(%arg0: none) -> none {
// CHECK-NEXT: %0 = handshake.join %arg0 : none
// CHECK-NEXT: ibis.return %0 : none
// CHECK-NEXT: }
// CHECK-NEXT: }
ibis.class sym @HighLevel {
%this = ibis.this <@foo::@HighLevel>
ibis.var @single : memref<i32>
ibis.var @array : memref<10xi32>
ibis.method @foo() -> (i32, i32) {
%parent = ibis.path [
#ibis.step<parent : !ibis.scoperef<@foo::@HighLevel>>
]
%single = ibis.get_var %parent, @single : !ibis.scoperef<@foo::@HighLevel> -> memref<i32>
%array = ibis.get_var %parent, @array : !ibis.scoperef<@foo::@HighLevel> -> memref<10xi32>
%local = memref.alloca() : memref<i32>
%c32 = hw.constant 32 : i32
%out1, %out2 = ibis.sblock(%arg : i32 = %c32) -> (i32, i32) attributes {schedule = 1} {
%v = memref.load %local[] : memref<i32>
memref.store %arg, %local[] : memref<i32>
ibis.sblock.return %v, %v : i32, i32
}
ibis.return %out1, %out2 : i32, i32
}
ibis.method.df @bar(%arg0 : none) -> (none) {
%0 = handshake.join %arg0 : none
ibis.return %0 : none
}
}
// CHECK-LABEL: ibis.class sym @A {
// CHECK-NEXT: %this = ibis.this <@foo::@A>
// CHECK-NEXT: %in = ibis.port.input "in" sym @in : i1
// CHECK-NEXT: %out = ibis.port.output "out" sym @out : i1
// CHECK-NEXT: %AnonymousPort = ibis.port.input sym @AnonymousPort : i1
// CHECK-NEXT: }
// CHECK-LABEL: ibis.class sym @LowLevel {
// CHECK-NEXT: %this = ibis.this <@foo::@LowLevel>
// CHECK-NEXT: %LowLevel_in = ibis.port.input "LowLevel_in" sym @LowLevel_in : i1
// CHECK-NEXT: %LowLevel_out = ibis.port.output "LowLevel_out" sym @LowLevel_out : i1
// CHECK-NEXT: %in_wire, %in_wire.out = ibis.wire.input @in_wire : i1
// CHECK-NEXT: %true = hw.constant true
// CHECK-NEXT: %out_wire = ibis.wire.output @out_wire, %true : i1
// CHECK-NEXT: %a = ibis.instance @a, <@foo::@A>
// CHECK-NEXT: ibis.container sym @D {
// CHECK-NEXT: %this_0 = ibis.this <@foo::@D>
// CHECK-NEXT: %parent = ibis.path [#ibis.step<parent : !ibis.scoperef<@foo::@LowLevel>> : !ibis.scoperef<@foo::@LowLevel>]
// CHECK-NEXT: %parent.LowLevel_in.ref = ibis.get_port %parent, @LowLevel_in : !ibis.scoperef<@foo::@LowLevel> -> !ibis.portref<in i1>
// CHECK-NEXT: %parent.LowLevel_out.ref = ibis.get_port %parent, @LowLevel_out : !ibis.scoperef<@foo::@LowLevel> -> !ibis.portref<out i1>
// CHECK-NEXT: %true_1 = hw.constant true
// CHECK-NEXT: ibis.port.write %parent.LowLevel_in.ref, %true_1 : !ibis.portref<in i1>
// CHECK-NEXT: %parent.LowLevel_out.ref.val = ibis.port.read %parent.LowLevel_out.ref : !ibis.portref<out i1>
// CHECK-NEXT: %parent.a = ibis.path [#ibis.step<parent : !ibis.scoperef> : !ibis.scoperef, #ibis.step<child, @a : !ibis.scoperef<@foo::@A>> : !ibis.scoperef<@foo::@A>]
// CHECK-NEXT: %parent.a.in.ref = ibis.get_port %parent.a, @in : !ibis.scoperef<@foo::@A> -> !ibis.portref<in i1>
// CHECK-NEXT: %parent.a.out.ref = ibis.get_port %parent.a, @out : !ibis.scoperef<@foo::@A> -> !ibis.portref<out i1>
// CHECK-NEXT: ibis.port.write %parent.a.in.ref, %parent.LowLevel_out.ref.val : !ibis.portref<in i1>
// CHECK-NEXT: %parent.a.out.ref.val = ibis.port.read %parent.a.out.ref : !ibis.portref<out i1>
// CHECK-NEXT: hw.instance "foo" @externModule() -> ()
// CHECK-NEXT: }
// CHECK-NEXT: ibis.container "ThisName" sym @ThisSymbol {
// CHECK-NEXT: %this_0 = ibis.this <@foo::@ThisSymbol>
// CHECK-NEXT: }
// CHECK-NEXT: }
ibis.class sym @A {
%this = ibis.this <@foo::@A>
ibis.port.input "in" sym @in : i1
ibis.port.output "out" sym @out : i1
ibis.port.input sym @AnonymousPort : i1
}
ibis.class sym @LowLevel {
%this = ibis.this <@foo::@LowLevel>
ibis.port.input "LowLevel_in" sym @LowLevel_in : i1
ibis.port.output "LowLevel_out" sym @LowLevel_out : i1
%in_wire, %in_wire.val = ibis.wire.input @in_wire : i1
%true = hw.constant 1 : i1
%out_wire = ibis.wire.output @out_wire, %true : i1
// Instantiation
%a = ibis.instance @a, <@foo::@A>
ibis.container sym @D {
%this_d = ibis.this <@foo::@D>
%parent_C = ibis.path [
#ibis.step<parent : !ibis.scoperef<@foo::@LowLevel>>
]
// Test local read/writes
%LowLevel_in_p = ibis.get_port %parent_C, @LowLevel_in : !ibis.scoperef<@foo::@LowLevel> -> !ibis.portref<in i1>
%LowLevel_out_p = ibis.get_port %parent_C, @LowLevel_out : !ibis.scoperef<@foo::@LowLevel> -> !ibis.portref<out i1>
%t = hw.constant true
ibis.port.write %LowLevel_in_p, %t : !ibis.portref<in i1>
%LowLevel_out = ibis.port.read %LowLevel_out_p : !ibis.portref<out i1>
// Test cross-container read/writes
%A.in_parent = ibis.path [
#ibis.step<parent : !ibis.scoperef>,
#ibis.step<child , @a : !ibis.scoperef<@foo::@A>>
]
%A.in_p = ibis.get_port %A.in_parent, @in : !ibis.scoperef<@foo::@A> -> !ibis.portref<in i1>
%A.out_p = ibis.get_port %A.in_parent, @out : !ibis.scoperef<@foo::@A> -> !ibis.portref<out i1>
ibis.port.write %A.in_p, %LowLevel_out : !ibis.portref<in i1>
%A.out = ibis.port.read %A.out_p : !ibis.portref<out i1>
// Test hw.instance ops inside a container (symbol table usage)
hw.instance "foo" @externModule() -> ()
}
ibis.container "ThisName" sym @ThisSymbol {
%this2 = ibis.this <@foo::@ThisSymbol>
}
}
}
hw.module.extern @externModule()

View File

@ -0,0 +1,30 @@
// RUN: circt-opt --kanagawa-argify-blocks %s | FileCheck %s
// CHECK-LABEL: kanagawa.class sym @Argify {
// CHECK-NEXT: %this = kanagawa.this <@foo::@Argify>
// CHECK-NEXT: kanagawa.method @foo() -> () {
// CHECK-NEXT: %c32_i32 = hw.constant 32 : i32
// CHECK-NEXT: %0:2 = kanagawa.sblock.isolated (%arg0 : i32 = %c32_i32) -> (i32, i32) {
// CHECK-NEXT: %c31_i32 = hw.constant 31 : i32
// CHECK-NEXT: %1 = arith.addi %arg0, %c31_i32 : i32
// CHECK-NEXT: kanagawa.sblock.return %1, %arg0 : i32, i32
// CHECK-NEXT: }
// CHECK-NEXT: kanagawa.return
// CHECK-NEXT: }
// CHECK-NEXT: }
kanagawa.design @foo {
kanagawa.class sym @Argify {
%this = kanagawa.this <@foo::@Argify>
kanagawa.method @foo() {
%c32 = hw.constant 32 : i32
%0:2 = kanagawa.sblock() -> (i32, i32) {
%c31 = hw.constant 31 : i32
%res = arith.addi %c31, %c32 : i32
kanagawa.sblock.return %res, %c32 : i32, i32
}
kanagawa.return
}
}
}

View File

@ -1,16 +1,16 @@
// RUN: circt-opt --pass-pipeline="builtin.module(ibis.design(ibis.class(ibis-convert-cf-to-handshake)))" \
// RUN: circt-opt --pass-pipeline="builtin.module(kanagawa.design(kanagawa.class(kanagawa-convert-cf-to-handshake)))" \
// RUN: --allow-unregistered-dialect %s | FileCheck %s
// CHECK: ibis.method.df @foo(%[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32, %[[VAL_3:.*]]: i1, %[[VAL_4:.*]]: none) -> (i32, none) {
// CHECK: kanagawa.method.df @foo(%[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32, %[[VAL_3:.*]]: i1, %[[VAL_4:.*]]: none) -> (i32, none) {
// CHECK: %[[VAL_5:.*]] = handshake.merge %[[VAL_1]] : i32
// CHECK: %[[VAL_6:.*]] = handshake.merge %[[VAL_2]] : i32
// CHECK: %[[VAL_7:.*]] = handshake.merge %[[VAL_3]] : i1
// CHECK: %[[VAL_8:.*]] = handshake.buffer [2] fifo %[[VAL_7]] : i1
// CHECK: %[[VAL_9:.*]] = handshake.merge %[[VAL_4]] : none
// CHECK: %[[VAL_10:.*]] = ibis.sblock (%[[VAL_11:.*]] : i32 = %[[VAL_5]], %[[VAL_12:.*]] : i32 = %[[VAL_6]]) -> i32 attributes {maxThreads = 1 : i64} {
// CHECK: %[[VAL_10:.*]] = kanagawa.sblock (%[[VAL_11:.*]] : i32 = %[[VAL_5]], %[[VAL_12:.*]] : i32 = %[[VAL_6]]) -> i32 attributes {maxThreads = 1 : i64} {
// CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_11]], %[[VAL_12]] : i32
// CHECK: ibis.sblock.return %[[VAL_13]] : i32
// CHECK: kanagawa.sblock.return %[[VAL_13]] : i32
// CHECK: }
// CHECK: %[[VAL_14:.*]], %[[VAL_15:.*]] = handshake.cond_br %[[VAL_7]], %[[VAL_5]] : i32
// CHECK: %[[VAL_16:.*]], %[[VAL_17:.*]] = handshake.cond_br %[[VAL_7]], %[[VAL_9]] : none
@ -18,53 +18,53 @@
// CHECK: %[[VAL_20:.*]] = handshake.merge %[[VAL_14]] : i32
// CHECK: %[[VAL_21:.*]] = handshake.merge %[[VAL_18]] : i32
// CHECK: %[[VAL_22:.*]], %[[VAL_23:.*]] = handshake.control_merge %[[VAL_16]] : none, index
// CHECK: %[[VAL_24:.*]] = ibis.sblock (%[[VAL_25:.*]] : i32 = %[[VAL_21]], %[[VAL_26:.*]] : i32 = %[[VAL_20]]) -> i32 {
// CHECK: %[[VAL_24:.*]] = kanagawa.sblock (%[[VAL_25:.*]] : i32 = %[[VAL_21]], %[[VAL_26:.*]] : i32 = %[[VAL_20]]) -> i32 {
// CHECK: %[[VAL_27:.*]] = arith.subi %[[VAL_25]], %[[VAL_26]] : i32
// CHECK: ibis.sblock.return %[[VAL_27]] : i32
// CHECK: kanagawa.sblock.return %[[VAL_27]] : i32
// CHECK: }
// CHECK: %[[VAL_28:.*]] = handshake.br %[[VAL_22]] : none
// CHECK: %[[VAL_29:.*]] = handshake.br %[[VAL_24]] : i32
// CHECK: %[[VAL_30:.*]] = handshake.merge %[[VAL_15]] : i32
// CHECK: %[[VAL_31:.*]] = handshake.merge %[[VAL_19]] : i32
// CHECK: %[[VAL_32:.*]], %[[VAL_33:.*]] = handshake.control_merge %[[VAL_17]] : none, index
// CHECK: %[[VAL_34:.*]] = ibis.sblock (%[[VAL_35:.*]] : i32 = %[[VAL_31]], %[[VAL_36:.*]] : i32 = %[[VAL_30]]) -> i32 {
// CHECK: %[[VAL_34:.*]] = kanagawa.sblock (%[[VAL_35:.*]] : i32 = %[[VAL_31]], %[[VAL_36:.*]] : i32 = %[[VAL_30]]) -> i32 {
// CHECK: %[[VAL_37:.*]] = "foo.op2"(%[[VAL_35]], %[[VAL_36]]) : (i32, i32) -> i32
// CHECK: ibis.sblock.return %[[VAL_37]] : i32
// CHECK: kanagawa.sblock.return %[[VAL_37]] : i32
// CHECK: }
// CHECK: %[[VAL_38:.*]] = handshake.br %[[VAL_32]] : none
// CHECK: %[[VAL_39:.*]] = handshake.br %[[VAL_34]] : i32
// CHECK: %[[VAL_40:.*]] = handshake.mux %[[VAL_41:.*]] {{\[}}%[[VAL_39]], %[[VAL_29]]] : index, i32
// CHECK: %[[VAL_42:.*]] = handshake.mux %[[VAL_8]] {{\[}}%[[VAL_38]], %[[VAL_28]]] : i1, none
// CHECK: %[[VAL_41]] = arith.index_cast %[[VAL_8]] : i1 to index
// CHECK: ibis.return %[[VAL_40]], %[[VAL_42]] : i32, none
// CHECK: kanagawa.return %[[VAL_40]], %[[VAL_42]] : i32, none
// CHECK: }
ibis.design @foo {
ibis.class sym @ToHandshake {
%this = ibis.this <@foo::@ToHandshake>
// Just a simple test demonstrating the intended mixing of `ibis.sblock`s and
kanagawa.design @foo {
kanagawa.class sym @ToHandshake {
%this = kanagawa.this <@foo::@ToHandshake>
// Just a simple test demonstrating the intended mixing of `kanagawa.sblock`s and
// control flow operations. The meat of cf-to-handshake conversion is tested
// in the handshake dialect tests.
ibis.method @foo(%a: i32, %b: i32, %cond : i1) -> i32 {
%0 = ibis.sblock (%arg0 : i32 = %a, %arg1 : i32 = %b) -> i32 attributes {maxThreads = 1 : i64} {
kanagawa.method @foo(%a: i32, %b: i32, %cond : i1) -> i32 {
%0 = kanagawa.sblock (%arg0 : i32 = %a, %arg1 : i32 = %b) -> i32 attributes {maxThreads = 1 : i64} {
%4 = arith.addi %arg0, %arg1 : i32
ibis.sblock.return %4 : i32
kanagawa.sblock.return %4 : i32
}
cf.cond_br %cond, ^bb1(%a, %0 : i32, i32), ^bb2(%a, %0 : i32, i32)
^bb1(%11: i32, %21: i32): // pred: ^bb0
%31 = ibis.sblock (%arg0 : i32 = %21, %arg1 : i32 = %11) -> i32 {
%31 = kanagawa.sblock (%arg0 : i32 = %21, %arg1 : i32 = %11) -> i32 {
%4 = arith.subi %arg0, %arg1 : i32
ibis.sblock.return %4 : i32
kanagawa.sblock.return %4 : i32
}
cf.br ^bb4(%31 : i32)
^bb2(%12 : i32, %22 : i32):
%32 = ibis.sblock (%arg0 : i32 = %22, %arg1 : i32 = %12) -> i32 {
%32 = kanagawa.sblock (%arg0 : i32 = %22, %arg1 : i32 = %12) -> i32 {
%4 = "foo.op2"(%arg0, %arg1) : (i32, i32) -> i32
ibis.sblock.return %4 : i32
kanagawa.sblock.return %4 : i32
}
cf.br ^bb4(%32 : i32)
^bb4(%res : i32):
ibis.return %res : i32
kanagawa.return %res : i32
}
}
}

View File

@ -0,0 +1,85 @@
// RUN: circt-opt --allow-unregistered-dialect --split-input-file --kanagawa-clean-selfdrivers %s | FileCheck %s
kanagawa.design @D {
// CHECK-LABEL: kanagawa.container sym @C {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@C>
// CHECK: %[[VAL_1:.*]] = hw.wire %[[VAL_2:.*]] : i1
// CHECK: %[[VAL_3:.*]] = kanagawa.port.output "out" sym @out : i1
// CHECK: %[[VAL_2]] = hw.constant true
// CHECK: kanagawa.port.write %[[VAL_3]], %[[VAL_1]] : !kanagawa.portref<out i1>
// CHECK: }
kanagawa.container sym @C {
%this = kanagawa.this <@D::@C>
%in = kanagawa.port.input "in" sym @in : i1
%out = kanagawa.port.output "out" sym @out : i1
%true = hw.constant 1 : i1
kanagawa.port.write %in, %true : !kanagawa.portref<in i1>
%v = kanagawa.port.read %in : !kanagawa.portref<in i1>
kanagawa.port.write %out, %v : !kanagawa.portref<out i1>
}
}
// -----
kanagawa.design @D {
// CHECK-LABEL: kanagawa.container sym @Selfdriver {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@Selfdriver>
// CHECK: %[[VAL_1:.*]] = hw.wire %[[VAL_2:.*]] : i1
// CHECK: %[[VAL_3:.*]] = kanagawa.port.output "myIn" sym @in : i1
// CHECK: kanagawa.port.write %[[VAL_3]], %[[VAL_1]] : !kanagawa.portref<out i1>
// CHECK: %[[VAL_2]] = hw.constant true
// CHECK: }
// CHECK-LABEL: kanagawa.container sym @ParentReader {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@ParentReader>
// CHECK: %[[VAL_1:.*]] = kanagawa.container.instance @selfdriver, <@D::@Selfdriver>
// CHECK: %[[VAL_2:.*]] = kanagawa.get_port %[[VAL_1]], @in : !kanagawa.scoperef<@D::@Selfdriver> -> !kanagawa.portref<out i1>
// CHECK: %[[VAL_3:.*]] = kanagawa.port.read %[[VAL_2]] : !kanagawa.portref<out i1>
// CHECK: }
kanagawa.container sym @Selfdriver {
%this = kanagawa.this <@D::@Selfdriver>
%in = kanagawa.port.input "myIn" sym @in : i1
%true = hw.constant 1 : i1
kanagawa.port.write %in, %true : !kanagawa.portref<in i1>
}
kanagawa.container sym @ParentReader {
%this = kanagawa.this <@D::@ParentReader>
%selfdriver = kanagawa.container.instance @selfdriver, <@D::@Selfdriver>
%in_ref = kanagawa.get_port %selfdriver, @in : !kanagawa.scoperef<@D::@Selfdriver> -> !kanagawa.portref<out i1>
%in = kanagawa.port.read %in_ref : !kanagawa.portref<out i1>
}
}
// -----
kanagawa.design @D {
kanagawa.container sym @Foo {
%this = kanagawa.this <@D::@Foo>
%in = kanagawa.port.input "in" sym @in : i1
}
// CHECK-LABEL: kanagawa.container sym @ParentReaderWriter {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@ParentReaderWriter>
// CHECK: %[[VAL_1:.*]] = kanagawa.container.instance @f, <@D::@Foo>
// CHECK: %[[VAL_2:.*]] = kanagawa.get_port %[[VAL_1]], @in : !kanagawa.scoperef<@D::@Foo> -> !kanagawa.portref<in i1>
// CHECK: "foo.bar"(%[[VAL_3:.*]]) : (i1) -> ()
// CHECK: %[[VAL_3]] = hw.constant true
// CHECK: kanagawa.port.write %[[VAL_2]], %[[VAL_3]] : !kanagawa.portref<in i1>
// CHECK: }
kanagawa.container sym @ParentReaderWriter {
%this = kanagawa.this <@D::@ParentReaderWriter>
%f = kanagawa.container.instance @f, <@D::@Foo>
%in_wr_ref = kanagawa.get_port %f, @in : !kanagawa.scoperef<@D::@Foo> -> !kanagawa.portref<in i1>
%in_rd_ref = kanagawa.get_port %f, @in : !kanagawa.scoperef<@D::@Foo> -> !kanagawa.portref<out i1>
%v = kanagawa.port.read %in_rd_ref : !kanagawa.portref<out i1>
"foo.bar"(%v) : (i1) -> ()
%true = hw.constant 1 : i1
kanagawa.port.write %in_wr_ref, %true : !kanagawa.portref<in i1>
}
}

View File

@ -0,0 +1,38 @@
// RUN: circt-opt --pass-pipeline='builtin.module(kanagawa.design(kanagawa-containerize))' %s | FileCheck %s
kanagawa.design @foo {
// CHECK-LABEL: kanagawa.container sym @A_B
// CHECK-LABEL: kanagawa.container "MyClassName" sym @MyClass
// CHECK-LABEL: kanagawa.container sym @A_B_0
// CHECK-LABEL: kanagawa.container sym @A_C
// CHECK-LABEL: kanagawa.container sym @A {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@foo::@A>
// CHECK: kanagawa.port.input "A_in" sym @A_in : i1
// CHECK: %[[VAL_1:.*]] = kanagawa.container.instance @myClass, <@foo::@MyClass>
// CHECK: %[[VAL_2:.*]] = kanagawa.container.instance @A_B_0, <@foo::@A_B_0>
// CHECK: %[[VAL_3:.*]] = kanagawa.container.instance @A_C, <@foo::@A_C>
// This container will alias with the @B inside @A, and thus checks the
// name uniquing logic.
kanagawa.container sym @A_B {
%this = kanagawa.this <@foo::@A_B>
}
kanagawa.class "MyClassName" sym @MyClass {
%this = kanagawa.this <@foo::@MyClass>
}
kanagawa.class sym @A {
%this = kanagawa.this <@foo::@A>
kanagawa.port.input "A_in" sym @A_in : i1
%myClass = kanagawa.instance @myClass, <@foo::@MyClass>
kanagawa.container sym @B {
%B_this = kanagawa.this <@foo::@B>
}
kanagawa.container sym @C {
%C_this = kanagawa.this <@foo::@C>
}
}
}

View File

@ -0,0 +1,178 @@
// RUN: circt-opt --split-input-file --kanagawa-convert-containers-to-hw %s | FileCheck %s
kanagawa.design @D {
// CHECK: hw.module @D_MyB(in %in_foo : i1 {inputAttr}, out out_foo : i1 {outputAttr}) {
// CHECK: hw.output %in_foo : i1
// CHECK: }
// CHECK: hw.module @D_AccessSibling(in %p_b_out_foo : i1, out p_b_in_foo : i1) {
// CHECK: hw.output %p_b_out_foo : i1
// CHECK: }
// CHECK: hw.module @Parent() {
// CHECK: %a.p_b_in_foo = hw.instance "a" @D_AccessSibling(p_b_out_foo: %b.out_foo: i1) -> (p_b_in_foo: i1)
// CHECK: %b.out_foo = hw.instance "b" @D_MyB(in_foo: %a.p_b_in_foo: i1) -> (out_foo: i1)
// CHECK: hw.output
// CHECK: }
kanagawa.container "MyB" sym @B {
%this = kanagawa.this <@D::@B>
// Test different port names vs. symbol names
%in = kanagawa.port.input "in_foo" sym @in : i1 {"inputAttr"}
%out = kanagawa.port.output "out_foo" sym @out : i1 {"outputAttr"}
// Loopback.
%v = kanagawa.port.read %in : !kanagawa.portref<in i1>
kanagawa.port.write %out, %v : !kanagawa.portref<out i1>
}
kanagawa.container sym @AccessSibling {
%this = kanagawa.this <@D::@AccessSibling>
%p_b_out = kanagawa.port.input "p_b_out_foo" sym @p_b_out : i1
%p_b_in = kanagawa.port.output "p_b_in_foo" sym @p_b_in : i1
kanagawa.port.write %p_b_in, %p_b_out.val : !kanagawa.portref<out i1>
%p_b_out.val = kanagawa.port.read %p_b_out : !kanagawa.portref<in i1>
}
kanagawa.container sym @Parent top_level {
%this = kanagawa.this <@D::@Parent>
%a = kanagawa.container.instance @a, <@D::@AccessSibling>
%a.p_b_out.ref = kanagawa.get_port %a, @p_b_out : !kanagawa.scoperef<@D::@AccessSibling> -> !kanagawa.portref<in i1>
%b.out.ref.val = kanagawa.port.read %b.out.ref : !kanagawa.portref<out i1>
kanagawa.port.write %a.p_b_out.ref, %b.out.ref.val : !kanagawa.portref<in i1>
%a.p_b_in.ref = kanagawa.get_port %a, @p_b_in : !kanagawa.scoperef<@D::@AccessSibling> -> !kanagawa.portref<out i1>
%a.p_b_in.ref.val = kanagawa.port.read %a.p_b_in.ref : !kanagawa.portref<out i1>
kanagawa.port.write %b.in.ref, %a.p_b_in.ref.val : !kanagawa.portref<in i1>
%b = kanagawa.container.instance @b, <@D::@B>
%b.out.ref = kanagawa.get_port %b, @out : !kanagawa.scoperef<@D::@B> -> !kanagawa.portref<out i1>
%b.in.ref = kanagawa.get_port %b, @in : !kanagawa.scoperef<@D::@B> -> !kanagawa.portref<in i1>
}
}
// -----
// Test that we can instantiate and get ports of a container from a hw.module.
kanagawa.design @D {
// CHECK: hw.module @D_C(in %in_foo : i1, out out_foo : i1) {
// CHECK: hw.output %in_foo : i1
// CHECK: }
// CHECK: hw.module @Top() {
// CHECK: %c.out_foo = hw.instance "c" @D_C(in_foo: %c.out_foo: i1) -> (out_foo: i1)
// CHECK: hw.output
// CHECK: }
kanagawa.container sym @C {
%this = kanagawa.this <@D::@C>
%in = kanagawa.port.input "in_foo" sym @in : i1
%out = kanagawa.port.output "out_foo" sym @out : i1
%v = kanagawa.port.read %in : !kanagawa.portref<in i1>
kanagawa.port.write %out, %v : !kanagawa.portref<out i1>
}
}
hw.module @Top() {
%c = kanagawa.container.instance @c, <@D::@C>
%in = kanagawa.get_port %c, @in : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<in i1>
%out = kanagawa.get_port %c, @out : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<out i1>
%v = kanagawa.port.read %out : !kanagawa.portref<out i1>
kanagawa.port.write %in, %v : !kanagawa.portref<in i1>
}
// -----
// Test that we can also move non-kanagawa ops
kanagawa.design @D {
// CHECK-LABEL: hw.module @D_Inst(out out : i1) {
// CHECK: %[[VAL_0:.*]] = hw.constant true
// CHECK: hw.output %[[VAL_0]] : i1
// CHECK: }
// CHECK-LABEL: hw.module @D_Top() {
// CHECK: %[[VAL_0:.*]] = hw.instance "myInst" @D_Inst() -> (out: i1)
// CHECK: %[[VAL_1:.*]] = hw.constant true
// CHECK: %[[VAL_2:.*]] = comb.and bin %[[VAL_1]], %[[VAL_0]] : i1
// CHECK: hw.output
// CHECK: }
kanagawa.container sym @Inst {
%this = kanagawa.this <@D::@Inst>
%out = kanagawa.port.output "out" sym @out : i1
%true = hw.constant 1 : i1
kanagawa.port.write %out, %true : !kanagawa.portref<out i1>
}
kanagawa.container sym @Top {
%this = kanagawa.this <@D::@Top>
%myInst = kanagawa.container.instance @myInst, <@D::@Inst>
%true = hw.constant 1 : i1
%out.ref = kanagawa.get_port %myInst, @out : !kanagawa.scoperef<@D::@Inst> -> !kanagawa.portref<out i1>
%out.v = kanagawa.port.read %out.ref : !kanagawa.portref<out i1>
%blake = comb.and bin %true, %out.v : i1
}
}
// -----
// Test that we can unique duplicate port names.
kanagawa.design @D {
// CHECK: hw.module @D_Top(in %clk : i1, in %clk_0 : i1, out out : i1, out out_0 : i1) {
// CHECK: hw.output %clk, %clk_0 : i1, i1
kanagawa.container sym @Top {
%this = kanagawa.this <@D::@Top>
%clk1 = kanagawa.port.input "clk" sym @clk1 : i1
%clk2 = kanagawa.port.input "clk" sym @clk2 : i1
%out1 = kanagawa.port.output "out" sym @out1 : i1
%out2 = kanagawa.port.output "out" sym @out2 : i1
%v1 = kanagawa.port.read %clk1 : !kanagawa.portref<in i1>
%v2 = kanagawa.port.read %clk2 : !kanagawa.portref<in i1>
kanagawa.port.write %out1, %v1 : !kanagawa.portref<out i1>
kanagawa.port.write %out2, %v2 : !kanagawa.portref<out i1>
}
}
// -----
// Test that we can de-alias module names.
// CHECK: hw.module @D_Foo_0() {
// CHECK: hw.output
// CHECK: }
// CHECK: hw.module @Foo_0() {
// CHECK: hw.output
// CHECK: }
// CHECK: hw.module.extern @D_Foo(in %theExternModule : i1)
// CHECK: hw.module.extern @Foo(in %theExternModule : i1)
kanagawa.design @D {
kanagawa.container "Foo" sym @A {
%this = kanagawa.this <@D::@A>
}
kanagawa.container "Foo" sym @B top_level {
%this = kanagawa.this <@D::@B>
}
}
hw.module.extern @D_Foo(in %theExternModule : i1)
hw.module.extern @Foo(in %theExternModule : i1)
// -----
// Test that containers with names that alias with the design op are not
// de-aliased.
// CHECK: hw.module @D
kanagawa.design @D {
kanagawa.container "D" sym @D top_level {
%this = kanagawa.this <@D::@D>
}
}

View File

@ -0,0 +1,33 @@
// RUN: circt-opt --pass-pipeline='builtin.module(kanagawa.design(kanagawa.class(kanagawa-convert-handshake-to-dc)))' %s | FileCheck %s
// Actual handshake-to-dc conversion is tested in the respective pass tests.
// This file just tests the kanagawa-specific hooks.
// CHECK-LABEL: kanagawa.class sym @ToDC {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@foo::@ToDC>
// CHECK: kanagawa.method.df @foo(%[[VAL_1:.*]]: !dc.value<i32>) -> !dc.value<i32> {
// CHECK: %[[VAL_2:.*]], %[[VAL_3:.*]] = dc.unpack %[[VAL_1]] : !dc.value<i32>
// CHECK: %[[VAL_4:.*]]:2 = dc.fork [2] %[[VAL_2]]
// CHECK: %[[VAL_5:.*]] = dc.pack %[[VAL_4]]#0, %[[VAL_3]] : i32
// CHECK: %[[VAL_6:.*]] = dc.pack %[[VAL_4]]#1, %[[VAL_3]] : i32
// CHECK: %[[VAL_7:.*]] = kanagawa.sblock.dc (%[[VAL_8:.*]] : !dc.value<i32> = %[[VAL_5]], %[[VAL_9:.*]] : !dc.value<i32> = %[[VAL_6]]) -> !dc.value<i32> {
// CHECK: %[[VAL_10:.*]] = arith.addi %[[VAL_8]], %[[VAL_9]] : i32
// CHECK: kanagawa.sblock.return %[[VAL_10]] : i32
// CHECK: }
// CHECK: kanagawa.return %[[VAL_7]] : !dc.value<i32>
// CHECK: }
// CHECK: }
kanagawa.design @foo {
kanagawa.class sym @ToDC {
%this = kanagawa.this <@foo::@ToDC>
kanagawa.method.df @foo(%arg0: i32) -> (i32) {
%o0, %o1 = handshake.fork [2] %arg0 : i32
%1 = kanagawa.sblock.isolated(%a0 : i32 = %o0, %a1 : i32 = %o1) -> i32 {
%res = arith.addi %a0, %a1 : i32
kanagawa.sblock.return %res : i32
}
kanagawa.return %1 : i32
}
}
}

View File

@ -0,0 +1,64 @@
// RUN: circt-opt --pass-pipeline='builtin.module(kanagawa.design(kanagawa.class(kanagawa.method(kanagawa-inline-sblocks))))' \
// RUN: --allow-unregistered-dialect %s | FileCheck %s
kanagawa.design @foo {
// CHECK-LABEL: kanagawa.class sym @Inline1 {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@foo::@Inline1>
// CHECK: kanagawa.method @foo(%[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32) -> () {
// CHECK: kanagawa.sblock.inline.begin {maxThreads = 1 : i64}
// CHECK: %[[VAL_3:.*]] = "foo.op1"(%[[VAL_1]], %[[VAL_2]]) : (i32, i32) -> i32
// CHECK: kanagawa.sblock.inline.end
// CHECK: kanagawa.return
// CHECK: }
// CHECK: }
kanagawa.class sym @Inline1 {
%this = kanagawa.this <@foo::@Inline1>
kanagawa.method @foo(%a : i32, %b : i32) {
%0 = kanagawa.sblock() -> (i32) attributes {maxThreads = 1} {
%res = "foo.op1"(%a, %b) : (i32, i32) -> i32
kanagawa.sblock.return %res : i32
}
kanagawa.return
}
}
// CHECK-LABEL: kanagawa.class sym @Inline2 {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@foo::@Inline2>
// CHECK: kanagawa.method @foo(%[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32) -> () {
// CHECK: "foo.unused1"() : () -> ()
// CHECK: kanagawa.sblock.inline.begin {maxThreads = 1 : i64}
// CHECK: %[[VAL_3:.*]] = "foo.op1"(%[[VAL_1]], %[[VAL_2]]) : (i32, i32) -> i32
// CHECK: kanagawa.sblock.inline.end
// CHECK: "foo.unused2"() : () -> ()
// CHECK: cf.br ^bb1
// CHECK: ^bb1:
// CHECK: "foo.unused3"() : () -> ()
// CHECK: %[[VAL_4:.*]] = "foo.op2"(%[[VAL_3]], %[[VAL_1]]) : (i32, i32) -> i32
// CHECK: "foo.unused4"() : () -> ()
// CHECK: kanagawa.return
// CHECK: }
// CHECK: }
kanagawa.class sym @Inline2 {
%this = kanagawa.this <@foo::@Inline2>
kanagawa.method @foo(%a : i32, %b : i32) {
"foo.unused1"() : () -> ()
%0 = kanagawa.sblock() -> (i32) attributes {maxThreads = 1} {
%res = "foo.op1"(%a, %b) : (i32, i32) -> i32
kanagawa.sblock.return %res : i32
}
"foo.unused2"() : () -> ()
cf.br ^bb1
^bb1:
"foo.unused3"() : () -> ()
%1 = kanagawa.sblock() -> (i32) {
%res = "foo.op2"(%0, %a) : (i32, i32) -> i32
kanagawa.sblock.return %res : i32
}
"foo.unused4"() : () -> ()
kanagawa.return
}
}
}

View File

@ -0,0 +1,37 @@
// RUN: circt-opt --pass-pipeline='builtin.module(kanagawa.design(kanagawa.class(kanagawa-convert-methods-to-containers)))' %s | FileCheck %s
// CHECK-LABEL: kanagawa.class sym @ToContainers {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@foo::@ToContainers>
// CHECK: kanagawa.container sym @foo {
// CHECK: %[[VAL_1:.*]] = kanagawa.this <@foo::@foo>
// CHECK: %[[VAL_2:.*]] = kanagawa.port.input "arg0" sym @arg0 : !dc.value<i32>
// CHECK: %[[VAL_3:.*]] = kanagawa.port.read %[[VAL_2]] : !kanagawa.portref<in !dc.value<i32>>
// CHECK: %[[VAL_4:.*]] = kanagawa.port.output "out0" sym @out0 : !dc.value<i32>
// CHECK: kanagawa.port.write %[[VAL_4]], %[[VAL_5:.*]] : !kanagawa.portref<out !dc.value<i32>>
// CHECK: %[[VAL_6:.*]], %[[VAL_7:.*]] = dc.unpack %[[VAL_3]] : !dc.value<i32>
// CHECK: %[[VAL_8:.*]]:2 = dc.fork [2] %[[VAL_6]]
// CHECK: %[[VAL_9:.*]] = dc.pack %[[VAL_8]]#0, %[[VAL_7]] : i32
// CHECK: %[[VAL_10:.*]] = dc.pack %[[VAL_8]]#1, %[[VAL_7]] : i32
// CHECK: %[[VAL_5]] = kanagawa.sblock.dc (%[[VAL_11:.*]] : !dc.value<i32> = %[[VAL_9]], %[[VAL_12:.*]] : !dc.value<i32> = %[[VAL_10]]) -> !dc.value<i32> {
// CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_11]], %[[VAL_12]] : i32
// CHECK: kanagawa.sblock.return %[[VAL_13]] : i32
// CHECK: }
// CHECK: }
// CHECK: }
kanagawa.design @foo {
kanagawa.class sym @ToContainers {
%this = kanagawa.this <@foo::@ToContainers>
kanagawa.method.df @foo(%arg0: !dc.value<i32>) -> !dc.value<i32> {
%token, %output = dc.unpack %arg0 : !dc.value<i32>
%0:2 = dc.fork [2] %token
%1 = dc.pack %0#0, %output : i32
%2 = dc.pack %0#1, %output : i32
%3 = kanagawa.sblock.dc (%arg1 : !dc.value<i32> = %1, %arg2 : !dc.value<i32> = %2) -> !dc.value<i32> {
%4 = arith.addi %arg1, %arg2 : i32
kanagawa.sblock.return %4 : i32
}
kanagawa.return %3 : !dc.value<i32>
}
}
}

View File

@ -0,0 +1,73 @@
// The ultimate tunneling test - by having 3 intermediate levels for both up-
// and downwards tunneling, we are sure test all the possible combinations of
// tunneling. This is more of a sanity check that everything works as expected.
// RUN: circt-opt --split-input-file --kanagawa-tunneling \
// RUN: --kanagawa-lower-portrefs --kanagawa-clean-selfdrivers \
// RUN: --kanagawa-convert-containers-to-hw
kanagawa.design @foo {
kanagawa.container sym @D_up {
%this = kanagawa.this <@foo::@D_up>
%d = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<child, @a_down : !kanagawa.scoperef> : !kanagawa.scoperef,
#kanagawa.step<child, @b : !kanagawa.scoperef> : !kanagawa.scoperef,
#kanagawa.step<child, @c : !kanagawa.scoperef> : !kanagawa.scoperef,
#kanagawa.step<child, @d : !kanagawa.scoperef<@D_down>> : !kanagawa.scoperef<@D_down>]
// Write an input port
%clk_ref = kanagawa.get_port %d, @clk_in : !kanagawa.scoperef<@D_down> -> !kanagawa.portref<in i1>
%clk = hw.constant 1 : i1
kanagawa.port.write %clk_ref, %clk : !kanagawa.portref<in i1>
// Read an input port
%clk_ref_2 = kanagawa.get_port %d, @clk_in : !kanagawa.scoperef<@D_down> -> !kanagawa.portref<out i1>
%clk_in_val = kanagawa.port.read %clk_ref_2 : !kanagawa.portref<out i1>
// Read an output port
%clk_out_ref = kanagawa.get_port %d, @clk_out : !kanagawa.scoperef<@D_down> -> !kanagawa.portref<out i1>
%clk_out_val = kanagawa.port.read %clk_out_ref : !kanagawa.portref<out i1>
}
kanagawa.container sym @C_up {
%this = kanagawa.this <@foo::@C_up>
%d = kanagawa.container.instance @d, @D_up
}
kanagawa.container sym @B_up {
%this = kanagawa.this <@foo::@B_up>
%c = kanagawa.container.instance @c, @C_up
}
kanagawa.container sym @A_up {
%this = kanagawa.this <@foo::@A_up>
%b = kanagawa.container.instance @b, @B_up
}
kanagawa.container sym @Top {
%this = kanagawa.this <@foo::@Top>
%a_down = kanagawa.container.instance @a_down, @A_down
%a_up = kanagawa.container.instance @a_up, @A_up
}
kanagawa.container sym @A_down {
%this = kanagawa.this <@foo::@A_down>
%b = kanagawa.container.instance @b, @B_down
}
kanagawa.container sym @B_down {
%this = kanagawa.this <@foo::@B_down>
%c = kanagawa.container.instance @c, @C_down
}
kanagawa.container sym @C_down {
%this = kanagawa.this <@foo::@C_down>
%d = kanagawa.container.instance @d, @D_down
}
kanagawa.container sym @D_down {
%this = kanagawa.this <@foo::@D_down>
%clk = kanagawa.port.input "clk_in" sym @clk_in : i1
%clk_out = kanagawa.port.output "clk_out" sym @clk_out : i1
%clk.val = kanagawa.port.read %clk : !kanagawa.portref<in i1>
kanagawa.port.write %clk_out, %clk.val : !kanagawa.portref<out i1>
}
}

View File

@ -0,0 +1,260 @@
// RUN: circt-opt --split-input-file --kanagawa-lower-portrefs %s | FileCheck %s
kanagawa.design @D {
kanagawa.container sym @C {
%this = kanagawa.this <@D::@C>
%in = kanagawa.port.input "in" sym @in : i1
%out = kanagawa.port.output "out" sym @out : i1
}
// CHECK-LABEL: kanagawa.container sym @AccessSibling {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@AccessSibling>
// CHECK: %[[VAL_1:.*]] = kanagawa.port.input "p_b_out" sym @p_b_out : i1
// CHECK: %[[VAL_2:.*]] = kanagawa.port.output "p_b_in" sym @p_b_in : i1
// CHECK: kanagawa.port.write %[[VAL_2]], %[[VAL_3:.*]] : !kanagawa.portref<out i1>
// CHECK: %[[VAL_3]] = kanagawa.port.read %[[VAL_1]] : !kanagawa.portref<in i1>
// CHECK: }
kanagawa.container sym @AccessSibling {
%this = kanagawa.this <@D::@AccessSibling>
%p_b_out = kanagawa.port.input "p_b_out" sym @p_b_out : !kanagawa.portref<out i1>
%p_b_out_val = kanagawa.port.read %p_b_out : !kanagawa.portref<in !kanagawa.portref<out i1>>
%p_b_in = kanagawa.port.input "p_b_in" sym @p_b_in : !kanagawa.portref<in i1>
%p_b_in_val = kanagawa.port.read %p_b_in : !kanagawa.portref<in !kanagawa.portref<in i1>>
// Loopback to ensure that value replacement is performed.
%v = kanagawa.port.read %p_b_out_val : !kanagawa.portref<out i1>
kanagawa.port.write %p_b_in_val, %v : !kanagawa.portref<in i1>
}
// CHECK-LABEL: kanagawa.container sym @Parent {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@Parent>
// CHECK: %[[VAL_1:.*]] = kanagawa.container.instance @a, <@D::@AccessSibling>
// CHECK: %[[VAL_2:.*]] = kanagawa.get_port %[[VAL_1]], @p_b_out : !kanagawa.scoperef<@D::@AccessSibling> -> !kanagawa.portref<in i1>
// CHECK: %[[VAL_3:.*]] = kanagawa.port.read %[[VAL_4:.*]] : !kanagawa.portref<out i1>
// CHECK: kanagawa.port.write %[[VAL_2]], %[[VAL_3]] : !kanagawa.portref<in i1>
// CHECK: %[[VAL_5:.*]] = kanagawa.get_port %[[VAL_1]], @p_b_in : !kanagawa.scoperef<@D::@AccessSibling> -> !kanagawa.portref<out i1>
// CHECK: %[[VAL_6:.*]] = kanagawa.port.read %[[VAL_5]] : !kanagawa.portref<out i1>
// CHECK: kanagawa.port.write %[[VAL_7:.*]], %[[VAL_6]] : !kanagawa.portref<in i1>
// CHECK: %[[VAL_8:.*]] = kanagawa.container.instance @b, <@D::@C>
// CHECK: %[[VAL_4]] = kanagawa.get_port %[[VAL_8]], @out : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<out i1>
// CHECK: %[[VAL_7]] = kanagawa.get_port %[[VAL_8]], @in : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<in i1>
// CHECK: }
kanagawa.container sym @Parent {
%this = kanagawa.this <@D::@Parent>
%a = kanagawa.container.instance @a, <@D::@AccessSibling>
%a.p_b_out = kanagawa.get_port %a, @p_b_out : !kanagawa.scoperef<@D::@AccessSibling> -> !kanagawa.portref<in !kanagawa.portref<out i1>>
kanagawa.port.write %a.p_b_out, %b.out : !kanagawa.portref<in !kanagawa.portref<out i1>>
%a.p_b_in = kanagawa.get_port %a, @p_b_in : !kanagawa.scoperef<@D::@AccessSibling> -> !kanagawa.portref<in !kanagawa.portref<in i1>>
kanagawa.port.write %a.p_b_in, %b.in : !kanagawa.portref<in !kanagawa.portref<in i1>>
%b = kanagawa.container.instance @b, <@D::@C>
%b.out = kanagawa.get_port %b, @out : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<out i1>
%b.in = kanagawa.get_port %b, @in : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<in i1>
}
}
// -----
kanagawa.design @D {
// CHECK-LABEL: kanagawa.container sym @ParentPortAccess {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@ParentPortAccess>
// CHECK: %[[VAL_1:.*]] = kanagawa.port.output "p_in" sym @p_in : i1
// CHECK: %[[VAL_2:.*]] = kanagawa.port.input "p_out" sym @p_out : i1
// CHECK: }
kanagawa.container sym @ParentPortAccess {
%this = kanagawa.this <@D::@ParentPortAccess>
%p_in = kanagawa.port.input "p_in" sym @p_in : !kanagawa.portref<in i1>
%p_in_val = kanagawa.port.read %p_in : !kanagawa.portref<in !kanagawa.portref<in i1>>
%p_out = kanagawa.port.input "p_out" sym @p_out : !kanagawa.portref<out i1>
%p_out_val = kanagawa.port.read %p_out : !kanagawa.portref<in !kanagawa.portref<out i1>>
}
// CHECK-LABEL: kanagawa.container sym @Parent {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@Parent>
// CHECK: %[[VAL_1:.*]] = kanagawa.container.instance @c, <@D::@ParentPortAccess>
// CHECK: %[[VAL_2:.*]] = kanagawa.get_port %[[VAL_1]], @p_in : !kanagawa.scoperef<@D::@ParentPortAccess> -> !kanagawa.portref<out i1>
// CHECK: %[[VAL_3:.*]] = kanagawa.port.read %[[VAL_2]] : !kanagawa.portref<out i1>
// CHECK: kanagawa.port.write %[[VAL_4:.*]], %[[VAL_3]] : !kanagawa.portref<in i1>
// CHECK: %[[VAL_5:.*]] = kanagawa.get_port %[[VAL_1]], @p_out : !kanagawa.scoperef<@D::@ParentPortAccess> -> !kanagawa.portref<in i1>
// CHECK: %[[VAL_6:.*]] = kanagawa.port.read %[[VAL_7:.*]] : !kanagawa.portref<out i1>
// CHECK: kanagawa.port.write %[[VAL_5]], %[[VAL_6]] : !kanagawa.portref<in i1>
// CHECK: %[[VAL_4]] = kanagawa.port.input "in" sym @in : i1
// CHECK: %[[VAL_7]] = kanagawa.port.output "out" sym @out : i1
// CHECK: }
kanagawa.container sym @Parent {
%this = kanagawa.this <@D::@Parent>
%c = kanagawa.container.instance @c, <@D::@ParentPortAccess>
%c.p_in = kanagawa.get_port %c, @p_in : !kanagawa.scoperef<@D::@ParentPortAccess> -> !kanagawa.portref<in !kanagawa.portref<in i1>>
kanagawa.port.write %c.p_in, %in : !kanagawa.portref<in !kanagawa.portref<in i1>>
%c.p_out = kanagawa.get_port %c, @p_out : !kanagawa.scoperef<@D::@ParentPortAccess> -> !kanagawa.portref<in !kanagawa.portref<out i1>>
kanagawa.port.write %c.p_out, %out : !kanagawa.portref<in !kanagawa.portref<out i1>>
%in = kanagawa.port.input "in" sym @in : i1
%out = kanagawa.port.output "out" sym @out : i1
}
}
// -----
kanagawa.design @D {
// C1 child -> P1 parent -> P2 parent -> C2 child -> C3 child
// CHECK-LABEL: kanagawa.container sym @C1 {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@C1>
// CHECK: %[[VAL_1:.*]] = kanagawa.port.output "parent_parent_c2_c3_in" sym @parent_parent_c2_c3_in : i1
// CHECK: kanagawa.port.write %[[VAL_1]], %[[VAL_2:.*]] : !kanagawa.portref<out i1>
// CHECK: %[[VAL_3:.*]] = kanagawa.port.input "parent_parent_c2_c3_out" sym @parent_parent_c2_c3_out : i1
// CHECK: %[[VAL_2]] = kanagawa.port.read %[[VAL_3]] : !kanagawa.portref<in i1>
// CHECK: }
kanagawa.container sym @C1 {
%this = kanagawa.this <@D::@C1>
%parent_parent_c2_c3_in = kanagawa.port.input "parent_parent_c2_c3_in" sym @parent_parent_c2_c3_in : !kanagawa.portref<in i1>
%parent_parent_c2_c3_out = kanagawa.port.input "parent_parent_c2_c3_out" sym @parent_parent_c2_c3_out : !kanagawa.portref<out i1>
// Assignment drivers - unwrap the ports and roundtrip read-write.
%parent_b_in_unwrapped = kanagawa.port.read %parent_parent_c2_c3_in : !kanagawa.portref<in !kanagawa.portref<in i1>>
%parent_b_out_unwrapped = kanagawa.port.read %parent_parent_c2_c3_out : !kanagawa.portref<in !kanagawa.portref<out i1>>
%parent_b_out_value = kanagawa.port.read %parent_b_out_unwrapped : !kanagawa.portref<out i1>
kanagawa.port.write %parent_b_in_unwrapped, %parent_b_out_value : !kanagawa.portref<in i1>
}
// CHECK-LABEL: kanagawa.container sym @C2 {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@C2>
// CHECK: %[[VAL_1:.*]] = kanagawa.container.instance @c3, <@D::@C>
// CHECK: %[[VAL_2:.*]] = kanagawa.get_port %[[VAL_1]], @in : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<in i1>
// CHECK: %[[VAL_3:.*]] = kanagawa.get_port %[[VAL_1]], @out : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<out i1>
// CHECK: %[[VAL_4:.*]] = kanagawa.port.input "parent_parent_c2_c3_in" sym @parent_parent_c2_c3_in : i1
// CHECK: %[[VAL_5:.*]] = kanagawa.port.read %[[VAL_4]] : !kanagawa.portref<in i1>
// CHECK: kanagawa.port.write %[[VAL_2]], %[[VAL_5]] : !kanagawa.portref<in i1>
// CHECK: %[[VAL_6:.*]] = kanagawa.port.output "parent_parent_c2_c3_out" sym @parent_parent_c2_c3_out : i1
// CHECK: %[[VAL_7:.*]] = kanagawa.port.read %[[VAL_3]] : !kanagawa.portref<out i1>
// CHECK: kanagawa.port.write %[[VAL_6]], %[[VAL_7]] : !kanagawa.portref<out i1>
// CHECK: }
kanagawa.container sym @C2 {
%this = kanagawa.this <@D::@C2>
%c3 = kanagawa.container.instance @c3, <@D::@C>
%c3.in = kanagawa.get_port %c3, @in : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<in i1>
%c3.out = kanagawa.get_port %c3, @out : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<out i1>
%parent_parent_c2_c3_in = kanagawa.port.output "parent_parent_c2_c3_in" sym @parent_parent_c2_c3_in : !kanagawa.portref<in i1>
%parent_parent_c2_c3_out = kanagawa.port.output "parent_parent_c2_c3_out" sym @parent_parent_c2_c3_out : !kanagawa.portref<out i1>
kanagawa.port.write %parent_parent_c2_c3_in, %c3.in : !kanagawa.portref<out !kanagawa.portref<in i1>>
kanagawa.port.write %parent_parent_c2_c3_out, %c3.out : !kanagawa.portref<out !kanagawa.portref<out i1>>
}
kanagawa.container sym @C {
%this = kanagawa.this <@D::@C>
%in = kanagawa.port.input "in" sym @in : i1
%out = kanagawa.port.output "out" sym @out : i1
}
// CHECK-LABEL: kanagawa.container sym @P1 {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@P1>
// CHECK: %[[VAL_1:.*]] = kanagawa.container.instance @c1, <@D::@C1>
// CHECK: %[[VAL_2:.*]] = kanagawa.get_port %[[VAL_1]], @parent_parent_c2_c3_in : !kanagawa.scoperef<@D::@C1> -> !kanagawa.portref<out i1>
// CHECK: %[[VAL_3:.*]] = kanagawa.port.read %[[VAL_2]] : !kanagawa.portref<out i1>
// CHECK: %[[VAL_4:.*]] = kanagawa.get_port %[[VAL_1]], @parent_parent_c2_c3_out : !kanagawa.scoperef<@D::@C1> -> !kanagawa.portref<in i1>
// CHECK: %[[VAL_5:.*]] = kanagawa.port.read %[[VAL_6:.*]] : !kanagawa.portref<in i1>
// CHECK: kanagawa.port.write %[[VAL_4]], %[[VAL_5]] : !kanagawa.portref<in i1>
// CHECK: %[[VAL_7:.*]] = kanagawa.port.output "parent_parent_c2_c3_in" sym @parent_parent_c2_c3_in : i1
// CHECK: kanagawa.port.write %[[VAL_7]], %[[VAL_3]] : !kanagawa.portref<out i1>
// CHECK: %[[VAL_6]] = kanagawa.port.input "parent_parent_c2_c3_out" sym @parent_parent_c2_c3_out : i1
// CHECK: }
kanagawa.container sym @P1 {
%this = kanagawa.this <@D::@P1>
%c1 = kanagawa.container.instance @c1, <@D::@C1>
%c1.parent_parent_c2_c3_in = kanagawa.get_port %c1, @parent_parent_c2_c3_in : !kanagawa.scoperef<@D::@C1> -> !kanagawa.portref<in !kanagawa.portref<in i1>>
kanagawa.port.write %c1.parent_parent_c2_c3_in, %0 : !kanagawa.portref<in !kanagawa.portref<in i1>>
%c1.parent_parent_c2_c3_out = kanagawa.get_port %c1, @parent_parent_c2_c3_out : !kanagawa.scoperef<@D::@C1> -> !kanagawa.portref<in !kanagawa.portref<out i1>>
kanagawa.port.write %c1.parent_parent_c2_c3_out, %1 : !kanagawa.portref<in !kanagawa.portref<out i1>>
%parent_parent_c2_c3_in = kanagawa.port.input "parent_parent_c2_c3_in" sym @parent_parent_c2_c3_in : !kanagawa.portref<in i1>
%0 = kanagawa.port.read %parent_parent_c2_c3_in : !kanagawa.portref<in !kanagawa.portref<in i1>>
%parent_parent_c2_c3_out = kanagawa.port.input "parent_parent_c2_c3_out" sym @parent_parent_c2_c3_out : !kanagawa.portref<out i1>
%1 = kanagawa.port.read %parent_parent_c2_c3_out : !kanagawa.portref<in !kanagawa.portref<out i1>>
}
// CHECK-LABEL: kanagawa.container sym @P2 {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@P2>
// CHECK: %[[VAL_1:.*]] = kanagawa.container.instance @p1, <@D::@P1>
// CHECK: %[[VAL_2:.*]] = kanagawa.get_port %[[VAL_1]], @parent_parent_c2_c3_in : !kanagawa.scoperef<@D::@P1> -> !kanagawa.portref<out i1>
// CHECK: %[[VAL_3:.*]] = kanagawa.port.read %[[VAL_2]] : !kanagawa.portref<out i1>
// CHECK: kanagawa.port.write %[[VAL_4:.*]], %[[VAL_3]] : !kanagawa.portref<in i1>
// CHECK: %[[VAL_5:.*]] = kanagawa.get_port %[[VAL_1]], @parent_parent_c2_c3_out : !kanagawa.scoperef<@D::@P1> -> !kanagawa.portref<in i1>
// CHECK: %[[VAL_6:.*]] = kanagawa.port.read %[[VAL_7:.*]] : !kanagawa.portref<out i1>
// CHECK: kanagawa.port.write %[[VAL_5]], %[[VAL_6]] : !kanagawa.portref<in i1>
// CHECK: %[[VAL_8:.*]] = kanagawa.container.instance @c2, <@D::@C2>
// CHECK: %[[VAL_7]] = kanagawa.get_port %[[VAL_8]], @parent_parent_c2_c3_out : !kanagawa.scoperef<@D::@C2> -> !kanagawa.portref<out i1>
// CHECK: %[[VAL_4]] = kanagawa.port.input "parent_parent_c2_c3_in_fw" sym @parent_parent_c2_c3_in_fw : i1
// CHECK: %[[VAL_9:.*]] = kanagawa.port.read %[[VAL_4]] : !kanagawa.portref<in i1>
// CHECK: %[[VAL_10:.*]] = kanagawa.get_port %[[VAL_8]], @parent_parent_c2_c3_in : !kanagawa.scoperef<@D::@C2> -> !kanagawa.portref<in i1>
// CHECK: kanagawa.port.write %[[VAL_10]], %[[VAL_9]] : !kanagawa.portref<in i1>
// CHECK: }
kanagawa.container sym @P2 {
%this = kanagawa.this <@D::@P2>
%p1 = kanagawa.container.instance @p1, <@D::@P1>
%p1.parent_parent_c2_c3_in = kanagawa.get_port %p1, @parent_parent_c2_c3_in : !kanagawa.scoperef<@D::@P1> -> !kanagawa.portref<in !kanagawa.portref<in i1>>
kanagawa.port.write %p1.parent_parent_c2_c3_in, %1 : !kanagawa.portref<in !kanagawa.portref<in i1>>
%p1.parent_parent_c2_c3_out = kanagawa.get_port %p1, @parent_parent_c2_c3_out : !kanagawa.scoperef<@D::@P1> -> !kanagawa.portref<in !kanagawa.portref<out i1>>
kanagawa.port.write %p1.parent_parent_c2_c3_out, %0 : !kanagawa.portref<in !kanagawa.portref<out i1>>
%c2 = kanagawa.container.instance @c2, <@D::@C2>
%c2.parent_parent_c2_c3_out = kanagawa.get_port %c2, @parent_parent_c2_c3_out : !kanagawa.scoperef<@D::@C2> -> !kanagawa.portref<out !kanagawa.portref<out i1>>
%0 = kanagawa.port.read %c2.parent_parent_c2_c3_out : !kanagawa.portref<out !kanagawa.portref<out i1>>
%c2.parent_parent_c2_c3_in = kanagawa.get_port %c2, @parent_parent_c2_c3_in : !kanagawa.scoperef<@D::@C2> -> !kanagawa.portref<out !kanagawa.portref<in i1>>
%1 = kanagawa.port.read %c2.parent_parent_c2_c3_in : !kanagawa.portref<out !kanagawa.portref<in i1>>
}
}
// -----
kanagawa.design @D {
// CHECK-LABEL: kanagawa.container sym @AccessParent {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@AccessParent>
// CHECK: %[[VAL_1:.*]] = kanagawa.port.output "p_out" sym @p_out : i1
// CHECK: %[[VAL_2:.*]] = kanagawa.port.input "p_in" sym @p_in : i1
// CHECK: }
kanagawa.container sym @AccessParent {
%this = kanagawa.this <@D::@AccessParent>
%p_out = kanagawa.port.input "p_out" sym @p_out : !kanagawa.portref<in i1>
%p_out.val = kanagawa.port.read %p_out : !kanagawa.portref<in !kanagawa.portref<in i1>>
%p_in = kanagawa.port.input "p_in" sym @p_in : !kanagawa.portref<out i1>
%p_in.val = kanagawa.port.read %p_in : !kanagawa.portref<in !kanagawa.portref<out i1>>
}
// CHECK-LABEL: kanagawa.container sym @Parent {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@Parent>
// CHECK: %[[VAL_1:.*]] = kanagawa.port.input "in" sym @in : i1
// CHECK: %[[VAL_2:.*]] = kanagawa.port.read %[[VAL_1]] : !kanagawa.portref<in i1>
// CHECK: %[[VAL_3:.*]] = kanagawa.wire.output @in.rd, %[[VAL_2]] : i1
// CHECK: %[[VAL_4:.*]] = kanagawa.port.output "out" sym @out : i1
// CHECK: %[[VAL_5:.*]], %[[VAL_6:.*]] = kanagawa.wire.input @out.wr : i1
// CHECK: kanagawa.port.write %[[VAL_4]], %[[VAL_6]] : !kanagawa.portref<out i1>
// CHECK: %[[VAL_7:.*]] = kanagawa.container.instance @c, <@D::@AccessParent>
// CHECK: %[[VAL_8:.*]] = kanagawa.get_port %[[VAL_7]], @p_out : !kanagawa.scoperef<@D::@AccessParent> -> !kanagawa.portref<out i1>
// CHECK: %[[VAL_9:.*]] = kanagawa.port.read %[[VAL_8]] : !kanagawa.portref<out i1>
// CHECK: kanagawa.port.write %[[VAL_5]], %[[VAL_9]] : !kanagawa.portref<in i1>
// CHECK: %[[VAL_10:.*]] = kanagawa.get_port %[[VAL_7]], @p_in : !kanagawa.scoperef<@D::@AccessParent> -> !kanagawa.portref<in i1>
// CHECK: %[[VAL_11:.*]] = kanagawa.port.read %[[VAL_3]] : !kanagawa.portref<out i1>
// CHECK: kanagawa.port.write %[[VAL_10]], %[[VAL_11]] : !kanagawa.portref<in i1>
// CHECK: }
kanagawa.container sym @Parent {
%this = kanagawa.this <@D::@Parent>
%in = kanagawa.port.input "in" sym @in : i1
%in.val = kanagawa.port.read %in : !kanagawa.portref<in i1>
%in.rd = kanagawa.wire.output @in.rd, %in.val : i1
%out = kanagawa.port.output "out" sym @out : i1
%out.wr, %out.wr.out = kanagawa.wire.input @out.wr : i1
kanagawa.port.write %out, %out.wr.out : !kanagawa.portref<out i1>
%c = kanagawa.container.instance @c, <@D::@AccessParent>
%c.p_out.ref = kanagawa.get_port %c, @p_out : !kanagawa.scoperef<@D::@AccessParent> -> !kanagawa.portref<in !kanagawa.portref<in i1>>
kanagawa.port.write %c.p_out.ref, %out.wr : !kanagawa.portref<in !kanagawa.portref<in i1>>
%c.p_in.ref = kanagawa.get_port %c, @p_in : !kanagawa.scoperef<@D::@AccessParent> -> !kanagawa.portref<in !kanagawa.portref<out i1>>
kanagawa.port.write %c.p_in.ref, %in.rd : !kanagawa.portref<in !kanagawa.portref<out i1>>
}
}

View File

@ -0,0 +1,29 @@
// RUN: circt-opt --pass-pipeline="builtin.module(kanagawa.design(kanagawa.class(kanagawa.method.df(kanagawa.sblock.isolated(kanagawa-prepare-scheduling)))))" \
// RUN: --allow-unregistered-dialect %s | FileCheck %s
// CHECK: kanagawa.method.df @foo(%[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32) -> (i32, i32) {
// CHECK: %[[VAL_3:.*]]:2 = kanagawa.sblock.isolated (%[[VAL_4:.*]] : i32 = %[[VAL_1]], %[[VAL_5:.*]] : i32 = %[[VAL_2]]) -> (i32, i32) {
// CHECK: %[[VAL_6:.*]], %[[VAL_7:.*]], %[[VAL_8:.*]], %[[VAL_9:.*]] = kanagawa.pipeline.header
// CHECK: %[[VAL_10:.*]], %[[VAL_11:.*]], %[[VAL_12:.*]] = pipeline.unscheduled(%[[VAL_13:.*]] : i32 = %[[VAL_4]], %[[VAL_14:.*]] : i32 = %[[VAL_5]]) stall(%[[VAL_9]]) clock(%[[VAL_6]]) reset(%[[VAL_7]]) go(%[[VAL_8]]) entryEn(%[[VAL_15:.*]]) {operator_lib = @kanagawa_operator_library} -> (out0 : i32, out1 : i32) {
// CHECK: %[[VAL_16:.*]] = "foo.op1"(%[[VAL_13]], %[[VAL_14]]) {ssp.operator_type = @foo.op1} : (i32, i32) -> i32
// CHECK: pipeline.return %[[VAL_16]], %[[VAL_13]] : i32, i32
// CHECK: }
// CHECK: kanagawa.sblock.return %[[VAL_17:.*]], %[[VAL_18:.*]] : i32, i32
// CHECK: }
kanagawa.design @foo {
kanagawa.class sym @PrepareScheduling {
%this = kanagawa.this <@foo::@PrepareScheduling>
// A test wherein the returned values are either a value generated by an
// operation in the pipeline, or a value that's passed through the pipeline.
// The resulting IR should have all values passing through the newly created
// pipeline.
kanagawa.method.df @foo(%a: i32, %b: i32) -> (i32, i32) {
%0, %1 = kanagawa.sblock.isolated (%arg0 : i32 = %a, %arg1 : i32 = %b) -> (i32, i32) {
%4 = "foo.op1"(%arg0, %arg1) : (i32, i32) -> i32
kanagawa.sblock.return %4, %arg0 : i32, i32
}
kanagawa.return %0, %1 : i32, i32
}
}
}

View File

@ -0,0 +1,48 @@
// RUN: circt-opt --pass-pipeline='builtin.module(kanagawa.design(kanagawa.class(kanagawa.method(kanagawa-reblock))))' %s | FileCheck %s
// CHECK-LABEL: kanagawa.class sym @Reblock {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@foo::@Reblock>
// CHECK: kanagawa.method @foo(%[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32) -> i32 {
// CHECK: %[[VAL_3:.*]] = kanagawa.sblock () -> i32 {
// CHECK: %[[VAL_4:.*]] = arith.addi %[[VAL_1]], %[[VAL_2]] : i32
// CHECK: kanagawa.sblock.return %[[VAL_4]] : i32
// CHECK: }
// CHECK: %[[VAL_5:.*]] = kanagawa.sblock () -> i32 attributes {maxThreads = 2 : i64} {
// CHECK: %[[VAL_6:.*]] = arith.addi %[[VAL_3]], %[[VAL_2]] : i32
// CHECK: %[[VAL_7:.*]] = arith.addi %[[VAL_6]], %[[VAL_2]] : i32
// CHECK: kanagawa.sblock.return %[[VAL_7]] : i32
// CHECK: }
// CHECK: %[[VAL_8:.*]] = kanagawa.sblock () -> i32 {
// CHECK: %[[VAL_9:.*]] = arith.addi %[[VAL_5]], %[[VAL_2]] : i32
// CHECK: kanagawa.sblock.return %[[VAL_9]] : i32
// CHECK: }
// CHECK: cf.br ^bb1(%[[VAL_8]] : i32)
// CHECK: ^bb1(%[[VAL_10:.*]]: i32):
// CHECK: %[[VAL_11:.*]] = kanagawa.sblock () -> i32 {
// CHECK: %[[VAL_12:.*]] = arith.addi %[[VAL_10]], %[[VAL_8]] : i32
// CHECK: kanagawa.sblock.return %[[VAL_12]] : i32
// CHECK: }
// CHECK: kanagawa.return %[[VAL_11]] : i32
// CHECK: }
// CHECK: }
kanagawa.design @foo {
kanagawa.class sym @Reblock {
%this = kanagawa.this <@foo::@Reblock>
kanagawa.method @foo(%arg0 : i32, %arg1 : i32) -> i32 {
%0 = arith.addi %arg0, %arg1 : i32
kanagawa.sblock.inline.begin {maxThreads = 2}
%inner = arith.addi %0, %arg1 : i32
%1 = arith.addi %inner, %arg1 : i32
kanagawa.sblock.inline.end
%2 = arith.addi %1, %arg1 : i32
// %0 is used within the same MLIR block but outside the scope.
cf.br ^bb1(%2 : i32)
^bb1(%barg : i32):
%3 = arith.addi %barg, %2 : i32
// %1 is used in a different MLIR block (dominated by the sblock parent block).
kanagawa.return %3 : i32
}
}
}

View File

@ -1,7 +1,7 @@
// RUN: circt-opt --pass-pipeline='builtin.module(ibis-add-operator-library, ibis.design(ibis.class(ibis.method.df(ibis.sblock.isolated(pipeline-schedule-linear)))))' %s | \
// RUN: circt-opt --pass-pipeline='builtin.module(kanagawa-add-operator-library, kanagawa.design(kanagawa.class(kanagawa.method.df(kanagawa.sblock.isolated(pipeline-schedule-linear)))))' %s | \
// RUN: FileCheck %s
// CHECK-LABEL: ssp.library @ibis_operator_library {
// CHECK-LABEL: ssp.library @kanagawa_operator_library {
// CHECK: operator_type @comb.add [latency<1>]
// CHECK: operator_type @comb.sub [latency<1>]
// CHECK: operator_type @comb.mul [latency<2>]
@ -16,11 +16,11 @@
// CHECK: operator_type @comb.shrs [latency<1>]
// CHECK: }
// CHECK-LABEL: ibis.class sym @SchedulePipeline {
// CHECK: %[[VAL_0:.*]] = ibis.this <@foo::@SchedulePipeline>
// CHECK: ibis.method.df @foo(%[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32) -> i32 {
// CHECK: %[[VAL_3:.*]] = ibis.sblock.isolated (%[[VAL_4:.*]] : i32 = %[[VAL_1]], %[[VAL_5:.*]] : i32 = %[[VAL_2]]) -> i32 {
// CHECK: %[[VAL_6:.*]], %[[VAL_7:.*]], %[[VAL_8:.*]], %[[VAL_9:.*]] = ibis.pipeline.header
// CHECK-LABEL: kanagawa.class sym @SchedulePipeline {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@foo::@SchedulePipeline>
// CHECK: kanagawa.method.df @foo(%[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32) -> i32 {
// CHECK: %[[VAL_3:.*]] = kanagawa.sblock.isolated (%[[VAL_4:.*]] : i32 = %[[VAL_1]], %[[VAL_5:.*]] : i32 = %[[VAL_2]]) -> i32 {
// CHECK: %[[VAL_6:.*]], %[[VAL_7:.*]], %[[VAL_8:.*]], %[[VAL_9:.*]] = kanagawa.pipeline.header
// CHECK: %[[VAL_10:.*]], %[[VAL_11:.*]] = pipeline.scheduled(%[[VAL_12:.*]] : i32 = %[[VAL_4]], %[[VAL_13:.*]] : i32 = %[[VAL_5]]) stall(%[[VAL_9]]) clock(%[[VAL_6]]) reset(%[[VAL_7]]) go(%[[VAL_8]]) entryEn(%[[VAL_14:.*]]) -> (out0 : i32) {
// CHECK: %[[VAL_15:.*]] = comb.mul %[[VAL_12]], %[[VAL_13]] {ssp.operator_type = @comb.mul} : i32
// CHECK: pipeline.stage ^bb1
@ -38,32 +38,32 @@
// CHECK: ^bb5(%[[VAL_23:.*]]: i1):
// CHECK: pipeline.return %[[VAL_21]] : i32
// CHECK: }
// CHECK: ibis.sblock.return %[[VAL_24:.*]] : i32
// CHECK: kanagawa.sblock.return %[[VAL_24:.*]] : i32
// CHECK: }
// CHECK: ibis.return %[[VAL_3]] : i32
// CHECK: kanagawa.return %[[VAL_3]] : i32
// CHECK: }
// CHECK: }
ibis.design @foo {
ibis.class sym @SchedulePipeline {
%this = ibis.this <@foo::@SchedulePipeline>
kanagawa.design @foo {
kanagawa.class sym @SchedulePipeline {
%this = kanagawa.this <@foo::@SchedulePipeline>
// A test wherein the returned values are either a value generated by an
// operation in the pipeline, or a value that's passed through the pipeline.
// The resulting IR should have all values passing through the newly created
// pipeline.
ibis.method.df @foo(%a: i32, %b: i32) -> (i32) {
%0 = ibis.sblock.isolated (%arg2 : i32 = %a, %arg3 : i32 = %b) -> i32 {
%clock, %reset, %go, %stall = ibis.pipeline.header
%out0, %done = pipeline.unscheduled(%in0 : i32 = %arg2, %in1 : i32 = %arg3) stall(%stall) clock(%clock) reset(%reset) go(%go) entryEn(%s0_enable) {operator_lib = @ibis_operator_library} -> (out0 : i32) {
kanagawa.method.df @foo(%a: i32, %b: i32) -> (i32) {
%0 = kanagawa.sblock.isolated (%arg2 : i32 = %a, %arg3 : i32 = %b) -> i32 {
%clock, %reset, %go, %stall = kanagawa.pipeline.header
%out0, %done = pipeline.unscheduled(%in0 : i32 = %arg2, %in1 : i32 = %arg3) stall(%stall) clock(%clock) reset(%reset) go(%go) entryEn(%s0_enable) {operator_lib = @kanagawa_operator_library} -> (out0 : i32) {
%1 = comb.add %in0, %in1 {ssp.operator_type = @comb.add} : i32
%2 = comb.mul %in0, %in1 {ssp.operator_type = @comb.mul} : i32
%3 = comb.sub %1, %2 {ssp.operator_type = @comb.sub} : i32
%4 = comb.mul %3, %1 {ssp.operator_type = @comb.mul} : i32
pipeline.return %4 : i32
}
ibis.sblock.return %out0 : i32
kanagawa.sblock.return %out0 : i32
}
ibis.return %0 : i32
kanagawa.return %0 : i32
}
}
}

View File

@ -0,0 +1,314 @@
// RUN: circt-opt --split-input-file --kanagawa-tunneling %s | FileCheck %s
kanagawa.design @D {
kanagawa.container sym @C {
%this = kanagawa.this <@D::@C>
%in = kanagawa.port.input "in" sym @in : i1
%out = kanagawa.port.output "out" sym @out : i1
}
// CHECK-LABEL: kanagawa.container sym @AccessChild {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@AccessChild>
// CHECK: %[[VAL_1:.*]] = kanagawa.container.instance @c, <@D::@C>
// CHECK: %[[VAL_2:.*]] = kanagawa.get_port %[[VAL_1]], @out : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<out i1>
// CHECK: %[[VAL_3:.*]] = kanagawa.get_port %[[VAL_1]], @in : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<in i1>
// CHECK-NEXT: }
kanagawa.container sym @AccessChild {
%this = kanagawa.this <@D::@AccessChild>
%c = kanagawa.container.instance @c, <@D::@C>
%c_ref = kanagawa.path [
#kanagawa.step<child , @c : !kanagawa.scoperef<@D::@C>>
]
%c_in = kanagawa.get_port %c_ref, @in : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<in i1>
%c_out = kanagawa.get_port %c_ref, @out : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<out i1>
}
}
// -----
// CHECK-LABEL: // -----
kanagawa.design @D {
kanagawa.container sym @C {
%this = kanagawa.this <@D::@C>
%in = kanagawa.port.input "in" sym @in : i1
%out = kanagawa.port.output "out" sym @out : i1
}
// CHECK-LABEL: kanagawa.container sym @AccessSibling {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@AccessSibling>
// CHECK: %[[VAL_1:.*]] = kanagawa.port.input "[[VAL_1]]" sym @[[VAL_1]] : !kanagawa.portref<out i1>
// CHECK: %[[VAL_2:.*]] = kanagawa.port.read %[[VAL_1]] : !kanagawa.portref<in !kanagawa.portref<out i1>>
// CHECK: %[[VAL_3:.*]] = kanagawa.port.input "[[VAL_3]]" sym @[[VAL_3]] : !kanagawa.portref<in i1>
// CHECK: %[[VAL_4:.*]] = kanagawa.port.read %[[VAL_3]] : !kanagawa.portref<in !kanagawa.portref<in i1>>
// CHECK: }
kanagawa.container sym @AccessSibling {
%this = kanagawa.this <@D::@AccessSibling>
%sibling = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<child , @b : !kanagawa.scoperef<@D::@C>>
]
%c_in = kanagawa.get_port %sibling, @in : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<in i1>
%c_out = kanagawa.get_port %sibling, @out : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<out i1>
}
// CHECK-LABEL: kanagawa.container sym @Parent {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@Parent>
// CHECK: %[[VAL_1:.*]] = kanagawa.container.instance @a, <@D::@AccessSibling>
// CHECK: %[[VAL_2:.*]] = kanagawa.get_port %[[VAL_1]], @p_b_out.rd : !kanagawa.scoperef<@D::@AccessSibling> -> !kanagawa.portref<in !kanagawa.portref<out i1>>
// CHECK: kanagawa.port.write %[[VAL_2]], %[[VAL_3:.*]] : !kanagawa.portref<in !kanagawa.portref<out i1>>
// CHECK: %[[VAL_4:.*]] = kanagawa.get_port %[[VAL_1]], @p_b_in.wr : !kanagawa.scoperef<@D::@AccessSibling> -> !kanagawa.portref<in !kanagawa.portref<in i1>>
// CHECK: kanagawa.port.write %[[VAL_4]], %[[VAL_5:.*]] : !kanagawa.portref<in !kanagawa.portref<in i1>>
// CHECK: %[[VAL_6:.*]] = kanagawa.container.instance @b, <@D::@C>
// CHECK: %[[VAL_3]] = kanagawa.get_port %[[VAL_6]], @out : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<out i1>
// CHECK: %[[VAL_5]] = kanagawa.get_port %[[VAL_6]], @in : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<in i1>
// CHECK: }
kanagawa.container sym @Parent {
%this = kanagawa.this <@D::@Parent>
%a = kanagawa.container.instance @a, <@D::@AccessSibling>
%b = kanagawa.container.instance @b, <@D::@C>
}
}
// -----
// CHECK-LABEL: // -----
// "Full"/recursive case.
// C1 child -> P1 parent -> P2 parent -> C2 child -> C3 child
kanagawa.design @D {
// CHECK-LABEL: kanagawa.container sym @C1 {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@C1>
// CHECK: %[[VAL_1:.*]] = kanagawa.port.input "p_p_c2_c3_out.rd" sym @p_p_c2_c3_out.rd : !kanagawa.portref<out i1>
// CHECK: %[[VAL_2:.*]] = kanagawa.port.read %[[VAL_1]] : !kanagawa.portref<in !kanagawa.portref<out i1>>
// CHECK: %[[VAL_3:.*]] = kanagawa.port.input "p_p_c2_c3_in.wr" sym @p_p_c2_c3_in.wr : !kanagawa.portref<in i1>
// CHECK: %[[VAL_4:.*]] = kanagawa.port.read %[[VAL_3]] : !kanagawa.portref<in !kanagawa.portref<in i1>>
// CHECK: }
kanagawa.container sym @C1 {
%this = kanagawa.this <@D::@C1>
%c3 = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<child , @c2 : !kanagawa.scoperef>,
#kanagawa.step<child , @c3 : !kanagawa.scoperef<@D::@C>>
]
%c_in = kanagawa.get_port %c3, @in : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<in i1>
%c_out = kanagawa.get_port %c3, @out : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<out i1>
}
// CHECK-LABEL: kanagawa.container sym @C2 {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@C2>
// CHECK: %[[VAL_1:.*]] = kanagawa.container.instance @c3, <@D::@C>
// CHECK: %[[VAL_2:.*]] = kanagawa.get_port %[[VAL_1]], @out : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<out i1>
// CHECK: %[[VAL_3:.*]] = kanagawa.get_port %[[VAL_1]], @in : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<in i1>
// CHECK: %[[VAL_4:.*]] = kanagawa.port.output "p_p_c2_c3_out.rd" sym @p_p_c2_c3_out.rd : !kanagawa.portref<out i1>
// CHECK: %[[VAL_5:.*]] = kanagawa.port.output "p_p_c2_c3_in.wr" sym @p_p_c2_c3_in.wr : !kanagawa.portref<in i1>
// CHECK: kanagawa.port.write %[[VAL_4]], %[[VAL_2]] : !kanagawa.portref<out !kanagawa.portref<out i1>>
// CHECK: kanagawa.port.write %[[VAL_5]], %[[VAL_3]] : !kanagawa.portref<out !kanagawa.portref<in i1>>
// CHECK: }
kanagawa.container sym @C2 {
%this = kanagawa.this <@D::@C2>
%c3 = kanagawa.container.instance @c3, <@D::@C>
}
kanagawa.container sym @C {
%this = kanagawa.this <@D::@C>
%in = kanagawa.port.input "in" sym @in : i1
%out = kanagawa.port.output "out" sym @out : i1
}
// CHECK-LABEL: kanagawa.container sym @P1 {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@P1>
// CHECK: %[[VAL_1:.*]] = kanagawa.container.instance @c1, <@D::@C1>
// CHECK: %[[VAL_2:.*]] = kanagawa.get_port %[[VAL_1]], @p_p_c2_c3_out.rd : !kanagawa.scoperef<@D::@C1> -> !kanagawa.portref<in !kanagawa.portref<out i1>>
// CHECK: kanagawa.port.write %[[VAL_2]], %[[VAL_3:.*]] : !kanagawa.portref<in !kanagawa.portref<out i1>>
// CHECK: %[[VAL_4:.*]] = kanagawa.get_port %[[VAL_1]], @p_p_c2_c3_in.wr : !kanagawa.scoperef<@D::@C1> -> !kanagawa.portref<in !kanagawa.portref<in i1>>
// CHECK: kanagawa.port.write %[[VAL_4]], %[[VAL_5:.*]] : !kanagawa.portref<in !kanagawa.portref<in i1>>
// CHECK: %[[VAL_6:.*]] = kanagawa.port.input "p_p_c2_c3_out.rd" sym @p_p_c2_c3_out.rd : !kanagawa.portref<out i1>
// CHECK: %[[VAL_3]] = kanagawa.port.read %[[VAL_6]] : !kanagawa.portref<in !kanagawa.portref<out i1>>
// CHECK: %[[VAL_7:.*]] = kanagawa.port.input "p_p_c2_c3_in.wr" sym @p_p_c2_c3_in.wr : !kanagawa.portref<in i1>
// CHECK: %[[VAL_5]] = kanagawa.port.read %[[VAL_7]] : !kanagawa.portref<in !kanagawa.portref<in i1>>
// CHECK: }
kanagawa.container sym @P1 {
%this = kanagawa.this <@D::@P1>
%c1 = kanagawa.container.instance @c1, <@D::@C1>
}
// CHECK-LABEL: kanagawa.container sym @P2 {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@P2>
// CHECK: %[[VAL_1:.*]] = kanagawa.container.instance @p1, <@D::@P1>
// CHECK: %[[VAL_2:.*]] = kanagawa.get_port %[[VAL_1]], @p_p_c2_c3_out.rd : !kanagawa.scoperef<@D::@P1> -> !kanagawa.portref<in !kanagawa.portref<out i1>>
// CHECK: kanagawa.port.write %[[VAL_2]], %[[VAL_3:.*]] : !kanagawa.portref<in !kanagawa.portref<out i1>>
// CHECK: %[[VAL_4:.*]] = kanagawa.get_port %[[VAL_1]], @p_p_c2_c3_in.wr : !kanagawa.scoperef<@D::@P1> -> !kanagawa.portref<in !kanagawa.portref<in i1>>
// CHECK: kanagawa.port.write %[[VAL_4]], %[[VAL_5:.*]] : !kanagawa.portref<in !kanagawa.portref<in i1>>
// CHECK: %[[VAL_6:.*]] = kanagawa.container.instance @c2, <@D::@C2>
// CHECK: %[[VAL_7:.*]] = kanagawa.get_port %[[VAL_6]], @p_p_c2_c3_in.wr : !kanagawa.scoperef<@D::@C2> -> !kanagawa.portref<out !kanagawa.portref<in i1>>
// CHECK: %[[VAL_5]] = kanagawa.port.read %[[VAL_7]] : !kanagawa.portref<out !kanagawa.portref<in i1>>
// CHECK: %[[VAL_8:.*]] = kanagawa.get_port %[[VAL_6]], @p_p_c2_c3_out.rd : !kanagawa.scoperef<@D::@C2> -> !kanagawa.portref<out !kanagawa.portref<out i1>>
// CHECK: %[[VAL_3]] = kanagawa.port.read %[[VAL_8]] : !kanagawa.portref<out !kanagawa.portref<out i1>>
// CHECK: }
kanagawa.container sym @P2 {
%this = kanagawa.this <@D::@P2>
%p1 = kanagawa.container.instance @p1, <@D::@P1>
%c2 = kanagawa.container.instance @c2, <@D::@C2>
}
}
// -----
// CHECK-LABEL: // -----
kanagawa.design @D {
// CHECK-LABEL: kanagawa.container sym @AccessParent {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@AccessParent>
// CHECK: %[[VAL_1:.*]] = kanagawa.port.input "p_out.wr" sym @p_out.wr : !kanagawa.portref<in i1>
// CHECK: %[[VAL_2:.*]] = kanagawa.port.read %[[VAL_1]] : !kanagawa.portref<in !kanagawa.portref<in i1>>
// CHECK: %[[VAL_3:.*]] = kanagawa.port.input "p_in.rd" sym @p_in.rd : !kanagawa.portref<out i1>
// CHECK: %[[VAL_4:.*]] = kanagawa.port.read %[[VAL_3]] : !kanagawa.portref<in !kanagawa.portref<out i1>>
// CHECK: }
kanagawa.container sym @AccessParent {
%this = kanagawa.this <@D::@AccessParent>
%p = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef<@D::@Parent>>
]
// get_port states the intended usage of the port. Hence we should be able to
// request a parent input port as an output port (readable), and vice versa.
// This will insert wires in the target container to facilitate the direction
// flip.
%p_in_ref = kanagawa.get_port %p, @in : !kanagawa.scoperef<@D::@Parent> -> !kanagawa.portref<out i1>
%p_out_ref = kanagawa.get_port %p, @out : !kanagawa.scoperef<@D::@Parent> -> !kanagawa.portref<in i1>
}
// CHECK-LABEL: kanagawa.container sym @Parent {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@D::@Parent>
// CHECK: %[[VAL_1:.*]] = kanagawa.port.input "in" sym @in : i1
// CHECK: %[[VAL_2:.*]] = kanagawa.port.read %[[VAL_1]] : !kanagawa.portref<in i1>
// CHECK: %[[VAL_3:.*]] = kanagawa.wire.output @in.rd, %[[VAL_2]] : i1
// CHECK: %[[VAL_4:.*]] = kanagawa.port.output "out" sym @out : i1
// CHECK: %[[VAL_5:.*]], %[[VAL_6:.*]] = kanagawa.wire.input @out.wr : i1
// CHECK: kanagawa.port.write %[[VAL_4]], %[[VAL_6]] : !kanagawa.portref<out i1>
// CHECK: %[[VAL_7:.*]] = kanagawa.container.instance @c, <@D::@AccessParent>
// CHECK: %[[VAL_8:.*]] = kanagawa.get_port %[[VAL_7]], @p_out.wr : !kanagawa.scoperef<@D::@AccessParent> -> !kanagawa.portref<in !kanagawa.portref<in i1>>
// CHECK: kanagawa.port.write %[[VAL_8]], %[[VAL_5]] : !kanagawa.portref<in !kanagawa.portref<in i1>>
// CHECK: %[[VAL_9:.*]] = kanagawa.get_port %[[VAL_7]], @p_in.rd : !kanagawa.scoperef<@D::@AccessParent> -> !kanagawa.portref<in !kanagawa.portref<out i1>>
// CHECK: kanagawa.port.write %[[VAL_9]], %[[VAL_3]] : !kanagawa.portref<in !kanagawa.portref<out i1>>
// CHECK: }
kanagawa.container sym @Parent {
%this = kanagawa.this <@D::@Parent>
%in = kanagawa.port.input "in" sym @in : i1
%out = kanagawa.port.output "out" sym @out : i1
%c = kanagawa.container.instance @c, <@D::@AccessParent>
}
}
// -----
// CHECK-LABEL: // -----
kanagawa.design @D {
kanagawa.container sym @C {
%this = kanagawa.this <@D::@C>
%in = kanagawa.port.input "in" sym @in : i1
%out = kanagawa.port.output "out" sym @out : i1
}
// TODO: support this case. Too hard to support now. Problem is that hw.module
// cannot live within an kanagawa.design, but we need to run this pass on the
// kanagawa.design op. I don't think it's critical that we support this case currently.
// COM: CHECK-LABEL: hw.module @AccessChildFromHW() {
// COM: CHECK: %[[VAL_0:.*]] = kanagawa.container.instance @c, <@D::@C>
// COM: CHECK: %[[VAL_1:.*]] = kanagawa.get_port %[[VAL_0]], @out : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<out i1>
// COM: CHECK: %[[VAL_2:.*]] = kanagawa.get_port %[[VAL_0]], @in : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<in i1>
// COM: CHECK: hw.output
// COM: CHECK: }
}
hw.module @AccessChildFromHW() {
%c = kanagawa.container.instance @c, <@D::@C>
%c_ref = kanagawa.path [
#kanagawa.step<child , @c : !kanagawa.scoperef<@D::@C>>
]
%c_in = kanagawa.get_port %c_ref, @in : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<in i1>
%c_out = kanagawa.get_port %c_ref, @out : !kanagawa.scoperef<@D::@C> -> !kanagawa.portref<out i1>
}
// -----
// CHECK-LABEL: // -----
kanagawa.design @D {
// The ultimate tunneling test - by having 3 intermediate levels for both up-
// and downwards tunneling, we are sure test all the possible combinations of
// tunneling.
kanagawa.container sym @D_up {
%this = kanagawa.this <@D::@D_up>
%d = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<child, @a_down : !kanagawa.scoperef> : !kanagawa.scoperef,
#kanagawa.step<child, @b : !kanagawa.scoperef> : !kanagawa.scoperef,
#kanagawa.step<child, @c : !kanagawa.scoperef> : !kanagawa.scoperef,
#kanagawa.step<child, @d : !kanagawa.scoperef<@D::@D_down>> : !kanagawa.scoperef<@D::@D_down>]
// Write an input port
%clk_ref = kanagawa.get_port %d, @clk_in : !kanagawa.scoperef<@D::@D_down> -> !kanagawa.portref<in i1>
%clk = hw.constant 1 : i1
kanagawa.port.write %clk_ref, %clk : !kanagawa.portref<in i1>
// Read an input port
%clk_ref_2 = kanagawa.get_port %d, @clk_in : !kanagawa.scoperef<@D::@D_down> -> !kanagawa.portref<out i1>
%clk_in_val = kanagawa.port.read %clk_ref_2 : !kanagawa.portref<out i1>
// Read an output port
%clk_out_ref = kanagawa.get_port %d, @clk_out : !kanagawa.scoperef<@D::@D_down> -> !kanagawa.portref<out i1>
%clk_out_val = kanagawa.port.read %clk_out_ref : !kanagawa.portref<out i1>
}
kanagawa.container sym @C_up {
%this = kanagawa.this <@D::@C_up>
%d = kanagawa.container.instance @d, <@D::@D_up>
}
kanagawa.container sym @B_up {
%this = kanagawa.this <@D::@B_up>
%c = kanagawa.container.instance @c, <@D::@C_up>
}
kanagawa.container sym @A_up {
%this = kanagawa.this <@D::@A_up>
%b = kanagawa.container.instance @b, <@D::@B_up>
}
kanagawa.container sym @Top {
%this = kanagawa.this <@D::@Top>
%a_down = kanagawa.container.instance @a_down, <@D::@A_down>
%a_up = kanagawa.container.instance @a_up, <@D::@A_up>
}
kanagawa.container sym @A_down {
%this = kanagawa.this <@D::@A_down>
%b = kanagawa.container.instance @b, <@D::@B_down>
}
kanagawa.container sym @B_down {
%this = kanagawa.this <@D::@B_down>
%c = kanagawa.container.instance @c, <@D::@C_down>
}
kanagawa.container sym @C_down {
%this = kanagawa.this <@D::@C_down>
%d = kanagawa.container.instance @d, <@D::@D_down>
}
kanagawa.container sym @D_down {
%this = kanagawa.this <@D::@D_down>
%clk = kanagawa.port.input "clk_in" sym @clk_in : i1
%clk_out = kanagawa.port.output "clk_out" sym @clk_out : i1
%clk.val = kanagawa.port.read %clk : !kanagawa.portref<in i1>
kanagawa.port.write %clk_out, %clk.val : !kanagawa.portref<out i1>
}
}

View File

@ -0,0 +1,64 @@
// RUN: circt-opt %s | circt-opt | FileCheck %s
// RUN: circt-opt %s --kanagawa-call-prep | circt-opt | FileCheck %s --check-prefix=PREP
// CHECK-LABEL: kanagawa.class sym @C {
// CHECK: kanagawa.method @getAndSet(%x: ui32) -> ui32 {
// CHECK: kanagawa.return %x : ui32
// CHECK: kanagawa.method @returnNothingWithRet() -> () {
// CHECK: kanagawa.return
// PREP-LABEL: kanagawa.class sym @C {
// PREP: kanagawa.method @getAndSet(%arg: !hw.struct<x: ui32>) -> ui32 {
// PREP: %x = hw.struct_explode %arg : !hw.struct<x: ui32>
// PREP: kanagawa.return %x : ui32
// PREP: kanagawa.method @returnNothingWithRet(%arg: !hw.struct<>) -> () {
// PREP: hw.struct_explode %arg : !hw.struct<>
// PREP: kanagawa.return
kanagawa.design @foo {
kanagawa.class sym @C {
%this = kanagawa.this <@foo::@C>
kanagawa.method @getAndSet(%x: ui32) -> ui32 {
kanagawa.return %x : ui32
}
kanagawa.method @returnNothingWithRet() {
kanagawa.return
}
}
// CHECK-LABEL: kanagawa.class sym @User {
// CHECK: [[c:%.+]] = kanagawa.instance @c, <@foo::@C>
// CHECK: kanagawa.method @getAndSetWrapper(%new_value: ui32) -> ui32 {
// CHECK: [[x:%.+]] = kanagawa.call <@foo::@getAndSet>(%new_value) : (ui32) -> ui32
// CHECK: kanagawa.return [[x]] : ui32
// CHECK: kanagawa.method @getAndSetDup(%new_value: ui32) -> ui32 {
// CHECK: [[x:%.+]] = kanagawa.call <@foo::@getAndSet>(%new_value) : (ui32) -> ui32
// CHECK: kanagawa.return [[x]] : ui32
// PREP-LABEL: kanagawa.class sym @User {
// PREP: [[c:%.+]] = kanagawa.instance @c, <@foo::@C>
// PREP: kanagawa.method @getAndSetWrapper(%arg: !hw.struct<new_value: ui32>) -> ui32 {
// PREP: %new_value = hw.struct_explode %arg : !hw.struct<new_value: ui32>
// PREP: [[STRUCT1:%.+]] = hw.struct_create (%new_value) {sv.namehint = "getAndSet_args_called_from_getAndSetWrapper"} : !hw.struct<x: ui32>
// PREP: [[CALLRES1:%.+]] = kanagawa.call <@foo::@getAndSet>([[STRUCT1]]) : (!hw.struct<x: ui32>) -> ui32
// PREP: kanagawa.method @getAndSetDup(%arg: !hw.struct<new_value: ui32>) -> ui32 {
// PREP: %new_value = hw.struct_explode %arg : !hw.struct<new_value: ui32>
// PREP: [[STRUCT2:%.+]] = hw.struct_create (%new_value) {sv.namehint = "getAndSet_args_called_from_getAndSetDup"} : !hw.struct<x: ui32>
// PREP: [[CALLRES2:%.+]] = kanagawa.call <@foo::@getAndSet>([[STRUCT2]]) : (!hw.struct<x: ui32>) -> ui32
// PREP: kanagawa.return [[CALLRES2]] : ui32
kanagawa.class sym @User {
%this = kanagawa.this <@foo::@User>
kanagawa.instance @c, <@foo::@C>
kanagawa.method @getAndSetWrapper(%new_value: ui32) -> ui32 {
%x = kanagawa.call <@foo::@getAndSet>(%new_value): (ui32) -> ui32
kanagawa.return %x : ui32
}
kanagawa.method @getAndSetDup(%new_value: ui32) -> ui32 {
%x = kanagawa.call <@foo::@getAndSet>(%new_value): (ui32) -> ui32
kanagawa.return %x : ui32
}
}
}

View File

@ -0,0 +1,43 @@
// RUN: circt-opt --split-input-file --allow-unregistered-dialect --kanagawa-tunneling --verify-diagnostics %s
kanagawa.design @foo {
kanagawa.container sym @Parent {
%this = kanagawa.this <@foo::@Parent>
%in = kanagawa.port.input "in" sym @in : i1
}
kanagawa.container sym @Orphan {
%this = kanagawa.this <@foo::@Orphan>
// expected-error @+2 {{'kanagawa.path' op cannot tunnel up from "Orphan" because it has no uses}}
// expected-error @+1 {{failed to legalize operation 'kanagawa.path' that was explicitly marked illegal}}
%parent = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef<@foo::@Parent>>
]
%p = kanagawa.get_port %parent, @in : !kanagawa.scoperef<@foo::@Parent> -> !kanagawa.portref<in i1>
}
}
// -----
kanagawa.design @foo {
kanagawa.container sym @Parent {
%this = kanagawa.this <@foo::@Parent>
%mc = kanagawa.container.instance @mc, <@foo::@MissingChild>
}
kanagawa.container sym @Child {
%this = kanagawa.this <@foo::@Child>
%in = kanagawa.port.input "in" sym @in : i1
}
kanagawa.container sym @MissingChild {
%this = kanagawa.this <@foo::@MissingChild>
// expected-error @+2 {{'kanagawa.path' op expected an instance named @c in @Parent but found none}}
// expected-error @+1 {{failed to legalize operation 'kanagawa.path' that was explicitly marked illegal}}
%parent = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<child , @c : !kanagawa.scoperef<@foo::@Child>>
]
%p = kanagawa.get_port %parent, @in : !kanagawa.scoperef<@foo::@Child> -> !kanagawa.portref<in i1>
}
}

View File

@ -0,0 +1,40 @@
// RUN: circt-opt --allow-unregistered-dialect --split-input-file --canonicalize --cse %s | FileCheck %s
kanagawa.design @foo {
// CHECK-LABEL: kanagawa.container sym @GetPortOnThis {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@foo::@GetPortOnThis>
// CHECK: %[[VAL_1:.*]] = kanagawa.port.input "in" sym @in : i1
// CHECK: "foo.user"(%[[VAL_1]]) : (!kanagawa.portref<in i1>) -> ()
// CHECK: }
kanagawa.container sym @GetPortOnThis {
%this = kanagawa.this <@foo::@GetPortOnThis>
%p = kanagawa.port.input "in" sym @in : i1
%p2 = kanagawa.get_port %this, @in : !kanagawa.scoperef<@foo::@GetPortOnThis> -> !kanagawa.portref<in i1>
"foo.user"(%p2) : (!kanagawa.portref<in i1>) -> ()
}
}
// -----
kanagawa.design @foo {
kanagawa.container sym @C {
%this = kanagawa.this <@foo::@C>
}
// CHECK-LABEL: kanagawa.container sym @AccessChild {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@foo::@AccessChild>
// CHECK: %[[VAL_1:.*]] = kanagawa.container.instance @c, <@foo::@C
// CHECK: "foo.user"(%[[VAL_1]]) : (!kanagawa.scoperef<@foo::@C>) -> ()
// CHECK: }
kanagawa.container sym @AccessChild {
%this = kanagawa.this <@foo::@AccessChild>
%c = kanagawa.container.instance @c, <@foo::@C>
%c_ref = kanagawa.path [
#kanagawa.step<child , @c : !kanagawa.scoperef<@foo::@C>>
]
"foo.user"(%c_ref) : (!kanagawa.scoperef<@foo::@C>) -> ()
}
}

View File

@ -0,0 +1,96 @@
// RUN: circt-opt --split-input-file --verify-diagnostics %s
kanagawa.design @foo {
kanagawa.class sym @C {
%this = kanagawa.this <@foo::@C>
kanagawa.method @typeMismatch1() -> (ui32, i32) {
// expected-error @+1 {{'kanagawa.return' op must have the same number of operands as the method has results}}
kanagawa.return
}
}
}
// -----
kanagawa.design @foo {
kanagawa.class sym @C {
%this = kanagawa.this <@foo::@C>
kanagawa.method @typeMismatch3() -> ui32 {
%c = hw.constant 1 : i8
// expected-error @+1 {{'kanagawa.return' op operand type ('i8') must match function return type ('ui32')}}
kanagawa.return %c : i8
}
}
}
// -----
kanagawa.design @foo {
// expected-error @+1 {{'kanagawa.class' op must contain only one 'kanagawa.this' operation}}
kanagawa.class sym @MultipleThis {
%this = kanagawa.this <@foo::@MultipleThis>
%this2 = kanagawa.this <@foo::@MultipleThis>
}
}
// -----
kanagawa.design @foo {
// expected-error @+1 {{'kanagawa.container' op must contain a 'kanagawa.this' operation}}
kanagawa.container sym @NoThis {
}
}
// -----
kanagawa.design @foo {
kanagawa.class sym @PathStepParentWithInstanceName {
%this = kanagawa.this <@foo::@PathStepParentWithInstanceName>
// expected-error @+1 {{kanagawa.step 'parent' may not specify an instance name}}
%p = kanagawa.path [#kanagawa.step<parent , @a : !kanagawa.scoperef>]
}
}
// -----
kanagawa.design @foo {
kanagawa.class sym @PathStepInvalidType {
%this = kanagawa.this <@foo::@PathStepParentWithInstanceName>
// expected-error @+1 {{kanagawa.step type must be an !kanagawa.scoperef type}}
%p = kanagawa.path [#kanagawa.step<parent : i1>]
}
}
// -----
kanagawa.design @foo {
kanagawa.class sym @PathStepChildMissingSymbol {
%this = kanagawa.this <@foo::@PathStepNonExistingChild>
// expected-error @+1 {{kanagawa.step 'child' must specify an instance name}}
%p = kanagawa.path [#kanagawa.step<child : !kanagawa.scoperef<@foo::@A>>]
}
}
// -----
kanagawa.design @foo {
kanagawa.class sym @InvalidVar {
%this = kanagawa.this <@foo::@C>
// expected-error @+1 {{'kanagawa.var' op attribute 'type' failed to satisfy constraint: any memref type}}
kanagawa.var @var : i32
}
}
// -----
kanagawa.design @foo {
kanagawa.class sym @InvalidReturn {
%this = kanagawa.this <@foo::@InvalidReturn>
kanagawa.method @foo() {
%c = hw.constant 1 : i32
// expected-error @+1 {{'kanagawa.sblock.return' op number of operands must match number of block outputs}}
%ret = kanagawa.sblock() -> i32 {
}
kanagawa.return
}
}
}

View File

@ -0,0 +1,74 @@
// RUN: circt-opt --hw-verify-irn --split-input-file --verify-diagnostics %s
kanagawa.design @foo {
kanagawa.class sym @MissingPort {
%this = kanagawa.this <@foo::@MissingPort>
// expected-error @+1 {{'kanagawa.get_port' op port '@C_in' does not exist in @MissingPort}}
%c_in = kanagawa.get_port %this, @C_in : !kanagawa.scoperef<@foo::@MissingPort> -> !kanagawa.portref<in i1>
}
}
// -----
kanagawa.design @foo {
kanagawa.class sym @InvalidGetVar2 {
%this = kanagawa.this <@foo::@InvalidGetVar2>
kanagawa.var @var : memref<i32>
kanagawa.method @foo() {
%parent = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef<@foo::@InvalidGetVar2>>
]
// expected-error @+1 {{'kanagawa.get_var' op dereferenced type ('memref<i1>') must match variable type ('memref<i32>')}}
%var = kanagawa.get_var %parent, @var : !kanagawa.scoperef<@foo::@InvalidGetVar2> -> memref<i1>
kanagawa.return
}
}
}
// -----
kanagawa.design @foo {
kanagawa.class sym @InvalidGetVar {
%this = kanagawa.this <@foo::@InvalidGetVar>
kanagawa.var @var : memref<i32>
kanagawa.method @foo() {
%parent = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef<@foo::@InvalidGetVar>>
]
// expected-error @+1 {{'kanagawa.get_var' op result #0 must be memref of any type values, but got 'i32'}}
%var = kanagawa.get_var %parent, @var : !kanagawa.scoperef<@foo::@InvalidGetVar> -> i32
kanagawa.return
}
}
}
// -----
kanagawa.design @foo {
kanagawa.class sym @PortTypeMismatch {
%this = kanagawa.this <@foo::@PortTypeMismatch>
kanagawa.port.input "in" sym @in : i1
// expected-error @+1 {{'kanagawa.get_port' op symbol '@in' refers to a port of type 'i1', but this op has type 'i2'}}
%c_in = kanagawa.get_port %this, @in : !kanagawa.scoperef<@foo::@PortTypeMismatch> -> !kanagawa.portref<in i2>
}
}
// -----
kanagawa.design @foo {
kanagawa.class sym @PathStepNonExistingChild {
%this = kanagawa.this <@foo::@PathStepNonExistingChild>
// expected-error @+1 {{'kanagawa.path' op kanagawa.step scoperef symbol '@A' does not exist}}
%p = kanagawa.path [#kanagawa.step<child , @a : !kanagawa.scoperef<@foo::@A>>]
}
}
// -----
kanagawa.design @foo {
kanagawa.class sym @PathStepNonExistingParent {
%this = kanagawa.this <@foo::@PathStepNonExistingParent>
// expected-error @+1 {{'kanagawa.path' op last kanagawa.step in path must specify a symbol for the scoperef}}
%p = kanagawa.path [#kanagawa.step<parent : !kanagawa.scoperef>]
}
}

View File

@ -0,0 +1,145 @@
// RUN: circt-opt %s | circt-opt | FileCheck %s
kanagawa.design @foo {
// CHECK-LABEL: kanagawa.class sym @HighLevel {
// CHECK-NEXT: %this = kanagawa.this <@foo::@HighLevel>
// CHECK-NEXT: kanagawa.var @single : memref<i32>
// CHECK-NEXT: kanagawa.var @array : memref<10xi32>
// CHECK-NEXT: kanagawa.method @foo() -> (i32, i32) {
// CHECK-NEXT: %parent = kanagawa.path [#kanagawa.step<parent : !kanagawa.scoperef<@foo::@HighLevel>> : !kanagawa.scoperef<@foo::@HighLevel>]
// CHECK-NEXT: %single = kanagawa.get_var %parent, @single : !kanagawa.scoperef<@foo::@HighLevel> -> memref<i32>
// CHECK-NEXT: %array = kanagawa.get_var %parent, @array : !kanagawa.scoperef<@foo::@HighLevel> -> memref<10xi32>
// CHECK-NEXT: %alloca = memref.alloca() : memref<i32>
// CHECK-NEXT: %c32_i32 = hw.constant 32 : i32
// CHECK-NEXT: %0:2 = kanagawa.sblock (%arg0 : i32 = %c32_i32) -> (i32, i32) attributes {schedule = 1 : i64} {
// CHECK-NEXT: %1 = memref.load %alloca[] : memref<i32>
// CHECK-NEXT: memref.store %arg0, %alloca[] : memref<i32>
// CHECK-NEXT: kanagawa.sblock.return %1, %1 : i32, i32
// CHECK-NEXT: }
// CHECK-NEXT: kanagawa.return %0#0, %0#1 : i32, i32
// CHECK-NEXT: }
// CHECK-NEXT: kanagawa.method.df @bar(%arg0: none) -> none {
// CHECK-NEXT: %0 = handshake.join %arg0 : none
// CHECK-NEXT: kanagawa.return %0 : none
// CHECK-NEXT: }
// CHECK-NEXT: }
kanagawa.class sym @HighLevel {
%this = kanagawa.this <@foo::@HighLevel>
kanagawa.var @single : memref<i32>
kanagawa.var @array : memref<10xi32>
kanagawa.method @foo() -> (i32, i32) {
%parent = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef<@foo::@HighLevel>>
]
%single = kanagawa.get_var %parent, @single : !kanagawa.scoperef<@foo::@HighLevel> -> memref<i32>
%array = kanagawa.get_var %parent, @array : !kanagawa.scoperef<@foo::@HighLevel> -> memref<10xi32>
%local = memref.alloca() : memref<i32>
%c32 = hw.constant 32 : i32
%out1, %out2 = kanagawa.sblock(%arg : i32 = %c32) -> (i32, i32) attributes {schedule = 1} {
%v = memref.load %local[] : memref<i32>
memref.store %arg, %local[] : memref<i32>
kanagawa.sblock.return %v, %v : i32, i32
}
kanagawa.return %out1, %out2 : i32, i32
}
kanagawa.method.df @bar(%arg0 : none) -> (none) {
%0 = handshake.join %arg0 : none
kanagawa.return %0 : none
}
}
// CHECK-LABEL: kanagawa.class sym @A {
// CHECK-NEXT: %this = kanagawa.this <@foo::@A>
// CHECK-NEXT: %in = kanagawa.port.input "in" sym @in : i1
// CHECK-NEXT: %out = kanagawa.port.output "out" sym @out : i1
// CHECK-NEXT: %AnonymousPort = kanagawa.port.input sym @AnonymousPort : i1
// CHECK-NEXT: }
// CHECK-LABEL: kanagawa.class sym @LowLevel {
// CHECK-NEXT: %this = kanagawa.this <@foo::@LowLevel>
// CHECK-NEXT: %LowLevel_in = kanagawa.port.input "LowLevel_in" sym @LowLevel_in : i1
// CHECK-NEXT: %LowLevel_out = kanagawa.port.output "LowLevel_out" sym @LowLevel_out : i1
// CHECK-NEXT: %in_wire, %in_wire.out = kanagawa.wire.input @in_wire : i1
// CHECK-NEXT: %true = hw.constant true
// CHECK-NEXT: %out_wire = kanagawa.wire.output @out_wire, %true : i1
// CHECK-NEXT: %a = kanagawa.instance @a, <@foo::@A>
// CHECK-NEXT: kanagawa.container sym @D {
// CHECK-NEXT: %this_0 = kanagawa.this <@foo::@D>
// CHECK-NEXT: %parent = kanagawa.path [#kanagawa.step<parent : !kanagawa.scoperef<@foo::@LowLevel>> : !kanagawa.scoperef<@foo::@LowLevel>]
// CHECK-NEXT: %parent.LowLevel_in.ref = kanagawa.get_port %parent, @LowLevel_in : !kanagawa.scoperef<@foo::@LowLevel> -> !kanagawa.portref<in i1>
// CHECK-NEXT: %parent.LowLevel_out.ref = kanagawa.get_port %parent, @LowLevel_out : !kanagawa.scoperef<@foo::@LowLevel> -> !kanagawa.portref<out i1>
// CHECK-NEXT: %true_1 = hw.constant true
// CHECK-NEXT: kanagawa.port.write %parent.LowLevel_in.ref, %true_1 : !kanagawa.portref<in i1>
// CHECK-NEXT: %parent.LowLevel_out.ref.val = kanagawa.port.read %parent.LowLevel_out.ref : !kanagawa.portref<out i1>
// CHECK-NEXT: %parent.a = kanagawa.path [#kanagawa.step<parent : !kanagawa.scoperef> : !kanagawa.scoperef, #kanagawa.step<child, @a : !kanagawa.scoperef<@foo::@A>> : !kanagawa.scoperef<@foo::@A>]
// CHECK-NEXT: %parent.a.in.ref = kanagawa.get_port %parent.a, @in : !kanagawa.scoperef<@foo::@A> -> !kanagawa.portref<in i1>
// CHECK-NEXT: %parent.a.out.ref = kanagawa.get_port %parent.a, @out : !kanagawa.scoperef<@foo::@A> -> !kanagawa.portref<out i1>
// CHECK-NEXT: kanagawa.port.write %parent.a.in.ref, %parent.LowLevel_out.ref.val : !kanagawa.portref<in i1>
// CHECK-NEXT: %parent.a.out.ref.val = kanagawa.port.read %parent.a.out.ref : !kanagawa.portref<out i1>
// CHECK-NEXT: hw.instance "foo" @externModule() -> ()
// CHECK-NEXT: }
// CHECK-NEXT: kanagawa.container "ThisName" sym @ThisSymbol {
// CHECK-NEXT: %this_0 = kanagawa.this <@foo::@ThisSymbol>
// CHECK-NEXT: }
// CHECK-NEXT: }
kanagawa.class sym @A {
%this = kanagawa.this <@foo::@A>
kanagawa.port.input "in" sym @in : i1
kanagawa.port.output "out" sym @out : i1
kanagawa.port.input sym @AnonymousPort : i1
}
kanagawa.class sym @LowLevel {
%this = kanagawa.this <@foo::@LowLevel>
kanagawa.port.input "LowLevel_in" sym @LowLevel_in : i1
kanagawa.port.output "LowLevel_out" sym @LowLevel_out : i1
%in_wire, %in_wire.val = kanagawa.wire.input @in_wire : i1
%true = hw.constant 1 : i1
%out_wire = kanagawa.wire.output @out_wire, %true : i1
// Instantiation
%a = kanagawa.instance @a, <@foo::@A>
kanagawa.container sym @D {
%this_d = kanagawa.this <@foo::@D>
%parent_C = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef<@foo::@LowLevel>>
]
// Test local read/writes
%LowLevel_in_p = kanagawa.get_port %parent_C, @LowLevel_in : !kanagawa.scoperef<@foo::@LowLevel> -> !kanagawa.portref<in i1>
%LowLevel_out_p = kanagawa.get_port %parent_C, @LowLevel_out : !kanagawa.scoperef<@foo::@LowLevel> -> !kanagawa.portref<out i1>
%t = hw.constant true
kanagawa.port.write %LowLevel_in_p, %t : !kanagawa.portref<in i1>
%LowLevel_out = kanagawa.port.read %LowLevel_out_p : !kanagawa.portref<out i1>
// Test cross-container read/writes
%A.in_parent = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef>,
#kanagawa.step<child , @a : !kanagawa.scoperef<@foo::@A>>
]
%A.in_p = kanagawa.get_port %A.in_parent, @in : !kanagawa.scoperef<@foo::@A> -> !kanagawa.portref<in i1>
%A.out_p = kanagawa.get_port %A.in_parent, @out : !kanagawa.scoperef<@foo::@A> -> !kanagawa.portref<out i1>
kanagawa.port.write %A.in_p, %LowLevel_out : !kanagawa.portref<in i1>
%A.out = kanagawa.port.read %A.out_p : !kanagawa.portref<out i1>
// Test hw.instance ops inside a container (symbol table usage)
hw.instance "foo" @externModule() -> ()
}
kanagawa.container "ThisName" sym @ThisSymbol {
%this2 = kanagawa.this <@foo::@ThisSymbol>
}
}
}
hw.module.extern @externModule()

View File

@ -21,8 +21,8 @@
// DIALECT-SAME: handshake
// DIALECT-SAME: hw
// DIALECT-SAME: hwarith
// DIALECT-SAME: ibis
// DIALECT-SAME: interop
// DIALECT-SAME: kanagawa
// DIALECT-SAME: llhd
// DIALECT-SAME: llvm
// DIALECT-SAME: memref

View File

@ -1,79 +0,0 @@
// XFAIL: *
// See https://github.com/llvm/circt/issues/6658
// RUN: ibistool %s --lo --post-ibis-ir | FileCheck %s --check-prefix=CHECK-POST-IBIS
// RUN: ibistool %s --lo --ir | FileCheck %s --check-prefix=CHECK-IR
// RUN: ibistool %s --lo --verilog | FileCheck %s --check-prefix=CHECK-VERILOG
// CHECK-POST-IBIS-LABEL: hw.module @A_B(
// CHECK-POST-IBIS-SAME: in %[[VAL_0:.*]] : !seq.clock, in %[[VAL_1:.*]] : i1, out p_out : i1) {
// CHECK-POST-IBIS: %[[VAL_2:.*]] = seq.compreg %[[VAL_1]], %[[VAL_0]] : i1
// CHECK-POST-IBIS: hw.output %[[VAL_2]] : i1
// CHECK-POST-IBIS: }
// CHECK-POST-IBIS-LABEL: hw.module @A(
// CHECK-POST-IBIS-SAME: in %[[VAL_0:.*]] : i1, in %[[VAL_1:.*]] : !seq.clock, out out : i1) {
// CHECK-POST-IBIS: %[[VAL_2:.*]] = hw.instance "A_B" @A_B(p_clk: %[[VAL_1]]: !seq.clock, p_in: %[[VAL_0]]: i1) -> (p_out: i1)
// CHECK-POST-IBIS: hw.output %[[VAL_2]] : i1
// CHECK-POST-IBIS: }
// CHECK-IR-LABEL: hw.module @A_B(
// CHECK-IR-SAME: in %[[VAL_0:.*]] : i1, in %[[VAL_1:.*]] : i1, out p_out : i1) {
// CHECK-IR: %[[VAL_2:.*]] = sv.reg : !hw.inout<i1>
// CHECK-IR: %[[VAL_3:.*]] = sv.read_inout %[[VAL_2]] : !hw.inout<i1>
// CHECK-IR: sv.alwaysff(posedge %[[VAL_0]]) {
// CHECK-IR: sv.passign %[[VAL_2]], %[[VAL_1]] : i1
// CHECK-IR: }
// CHECK-IR: hw.output %[[VAL_3]] : i1
// CHECK-IR: }
// CHECK-IR-LABEL: hw.module @A(
// CHECK-IR-SAME: in %[[VAL_0:.*]] : i1, in %[[VAL_1:.*]] : i1, out out : i1) {
// CHECK-IR: %[[VAL_2:.*]] = hw.instance "A_B" @A_B(p_clk: %[[VAL_1]]: i1, p_in: %[[VAL_0]]: i1) -> (p_out: i1)
// CHECK-IR: hw.output %[[VAL_2]] : i1
// CHECK-IR: }
// CHECK-VERILOG-LABEL: module A_B(
// CHECK-VERILOG: input p_clk,
// CHECK-VERILOG: p_in,
// CHECK-VERILOG: output p_out
// CHECK-VERILOG: );
// CHECK-VERILOG: reg r;
// CHECK-VERILOG: always_ff @(posedge p_clk)
// CHECK-VERILOG: r <= p_in;
// CHECK-VERILOG: assign p_out = r;
// CHECK-VERILOG: endmodule
// CHECK-VERILOG-LABEL: module A(
// CHECK-VERILOG: input in,
// CHECK-VERILOG: clk,
// CHECK-VERILOG: output out
// CHECK-VERILOG: );
// CHECK-VERILOG: A_B A_B (
// CHECK-VERILOG: .p_clk (clk),
// CHECK-VERILOG: .p_in (in),
// CHECK-VERILOG: .p_out (out)
// CHECK-VERILOG: );
// CHECK-VERILOG: endmodule
ibis.design @foo {
ibis.class sym @A {
%this = ibis.this @A
ibis.port.input "in" sym @in : i1
ibis.port.output "out" sym @out : i1
ibis.port.input "clk" sym @clk : !seq.clock
ibis.container@B {
%B_this = ibis.this @B
%parent = ibis.path [
#ibis.step<parent : !ibis.scoperef<@foo::@A>>
]
%a_in = ibis.get_port %parent, @in : !ibis.scoperef<@foo::@A> -> !ibis.portref<out i1>
%a_clk = ibis.get_port %parent, @clk : !ibis.scoperef<@foo::@A> -> !ibis.portref<out !seq.clock>
%a_out = ibis.get_port %parent, @out : !ibis.scoperef<@foo::@A> -> !ibis.portref<in i1>
%in = ibis.port.read %a_in : !ibis.portref<out i1>
%clk = ibis.port.read %a_clk : !ibis.portref<out !seq.clock>
%r = seq.compreg %in, %clk: i1
ibis.port.write %a_out, %r : !ibis.portref<in i1>
}
}
}

View File

@ -1,55 +1,55 @@
// RUN: ibistool --hi --post-ibis-ir %s | FileCheck %s
// RUN: kanagawatool --hi --post-kanagawa-ir %s | FileCheck %s
// CHECK-LABEL: ibis.class sym @ToHandshake {
// CHECK: %[[VAL_0:.*]] = ibis.this <@foo::@ToHandshake>
// CHECK: ibis.method @foo(%[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32, %[[VAL_3:.*]]: i1) -> i32 {
// CHECK: %[[VAL_4:.*]]:3 = ibis.sblock.isolated () -> (i32, i32, i32) {
// CHECK-LABEL: kanagawa.class sym @ToHandshake {
// CHECK: %[[VAL_0:.*]] = kanagawa.this <@foo::@ToHandshake>
// CHECK: kanagawa.method @foo(%[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32, %[[VAL_3:.*]]: i1) -> i32 {
// CHECK: %[[VAL_4:.*]]:3 = kanagawa.sblock.isolated () -> (i32, i32, i32) {
// CHECK: %[[VAL_5:.*]] = arith.constant 2 : i32
// CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32
// CHECK: %[[VAL_7:.*]] = arith.constant 0 : i32
// CHECK: ibis.sblock.return %[[VAL_5]], %[[VAL_6]], %[[VAL_7]] : i32, i32, i32
// CHECK: kanagawa.sblock.return %[[VAL_5]], %[[VAL_6]], %[[VAL_7]] : i32, i32, i32
// CHECK: }
// CHECK: cf.br ^bb1(%[[VAL_1]], %[[VAL_8:.*]]#2, %[[VAL_2]], %[[VAL_8]]#0, %[[VAL_8]]#1, %[[VAL_8]]#2 : i32, i32, i32, i32, i32, i32)
// CHECK: ^bb1(%[[VAL_9:.*]]: i32, %[[VAL_10:.*]]: i32, %[[VAL_11:.*]]: i32, %[[VAL_12:.*]]: i32, %[[VAL_13:.*]]: i32, %[[VAL_14:.*]]: i32):
// CHECK: %[[VAL_15:.*]] = ibis.sblock.isolated (%[[VAL_16:.*]] : i32 = %[[VAL_9]], %[[VAL_17:.*]] : i32 = %[[VAL_11]]) -> i1 {
// CHECK: %[[VAL_15:.*]] = kanagawa.sblock.isolated (%[[VAL_16:.*]] : i32 = %[[VAL_9]], %[[VAL_17:.*]] : i32 = %[[VAL_11]]) -> i1 {
// CHECK: %[[VAL_18:.*]] = arith.cmpi slt, %[[VAL_16]], %[[VAL_17]] : i32
// CHECK: ibis.sblock.return %[[VAL_18]] : i1
// CHECK: kanagawa.sblock.return %[[VAL_18]] : i1
// CHECK: }
// CHECK: cf.cond_br %[[VAL_15]], ^bb2(%[[VAL_11]], %[[VAL_12]], %[[VAL_13]], %[[VAL_14]], %[[VAL_9]], %[[VAL_10]] : i32, i32, i32, i32, i32, i32), ^bb6(%[[VAL_10]] : i32)
// CHECK: ^bb2(%[[VAL_19:.*]]: i32, %[[VAL_20:.*]]: i32, %[[VAL_21:.*]]: i32, %[[VAL_22:.*]]: i32, %[[VAL_23:.*]]: i32, %[[VAL_24:.*]]: i32):
// CHECK: %[[VAL_25:.*]] = ibis.sblock.isolated (%[[VAL_26:.*]] : i32 = %[[VAL_24]], %[[VAL_27:.*]] : i32 = %[[VAL_20]], %[[VAL_28:.*]] : i32 = %[[VAL_22]]) -> i1 {
// CHECK: %[[VAL_25:.*]] = kanagawa.sblock.isolated (%[[VAL_26:.*]] : i32 = %[[VAL_24]], %[[VAL_27:.*]] : i32 = %[[VAL_20]], %[[VAL_28:.*]] : i32 = %[[VAL_22]]) -> i1 {
// CHECK: %[[VAL_29:.*]] = arith.remsi %[[VAL_26]], %[[VAL_27]] : i32
// CHECK: %[[VAL_30:.*]] = arith.cmpi eq, %[[VAL_29]], %[[VAL_28]] : i32
// CHECK: ibis.sblock.return %[[VAL_30]] : i1
// CHECK: kanagawa.sblock.return %[[VAL_30]] : i1
// CHECK: }
// CHECK: cf.cond_br %[[VAL_25]], ^bb3(%[[VAL_19]], %[[VAL_20]], %[[VAL_21]], %[[VAL_22]], %[[VAL_23]], %[[VAL_24]] : i32, i32, i32, i32, i32, i32), ^bb4(%[[VAL_19]], %[[VAL_20]], %[[VAL_21]], %[[VAL_22]], %[[VAL_23]], %[[VAL_24]] : i32, i32, i32, i32, i32, i32)
// CHECK: ^bb3(%[[VAL_31:.*]]: i32, %[[VAL_32:.*]]: i32, %[[VAL_33:.*]]: i32, %[[VAL_34:.*]]: i32, %[[VAL_35:.*]]: i32, %[[VAL_36:.*]]: i32):
// CHECK: %[[VAL_37:.*]] = ibis.sblock.isolated (%[[VAL_38:.*]] : i32 = %[[VAL_36]], %[[VAL_39:.*]] : i32 = %[[VAL_35]]) -> i32 {
// CHECK: %[[VAL_37:.*]] = kanagawa.sblock.isolated (%[[VAL_38:.*]] : i32 = %[[VAL_36]], %[[VAL_39:.*]] : i32 = %[[VAL_35]]) -> i32 {
// CHECK: %[[VAL_40:.*]] = arith.addi %[[VAL_38]], %[[VAL_39]] : i32
// CHECK: ibis.sblock.return %[[VAL_40]] : i32
// CHECK: kanagawa.sblock.return %[[VAL_40]] : i32
// CHECK: }
// CHECK: cf.br ^bb5(%[[VAL_37]], %[[VAL_31]], %[[VAL_32]], %[[VAL_33]], %[[VAL_34]], %[[VAL_35]] : i32, i32, i32, i32, i32, i32)
// CHECK: ^bb4(%[[VAL_41:.*]]: i32, %[[VAL_42:.*]]: i32, %[[VAL_43:.*]]: i32, %[[VAL_44:.*]]: i32, %[[VAL_45:.*]]: i32, %[[VAL_46:.*]]: i32):
// CHECK: %[[VAL_47:.*]] = ibis.sblock.isolated (%[[VAL_48:.*]] : i32 = %[[VAL_46]], %[[VAL_49:.*]] : i32 = %[[VAL_45]]) -> i32 {
// CHECK: %[[VAL_47:.*]] = kanagawa.sblock.isolated (%[[VAL_48:.*]] : i32 = %[[VAL_46]], %[[VAL_49:.*]] : i32 = %[[VAL_45]]) -> i32 {
// CHECK: %[[VAL_50:.*]] = arith.subi %[[VAL_48]], %[[VAL_49]] : i32
// CHECK: ibis.sblock.return %[[VAL_50]] : i32
// CHECK: kanagawa.sblock.return %[[VAL_50]] : i32
// CHECK: }
// CHECK: cf.br ^bb5(%[[VAL_47]], %[[VAL_41]], %[[VAL_42]], %[[VAL_43]], %[[VAL_44]], %[[VAL_45]] : i32, i32, i32, i32, i32, i32)
// CHECK: ^bb5(%[[VAL_51:.*]]: i32, %[[VAL_52:.*]]: i32, %[[VAL_53:.*]]: i32, %[[VAL_54:.*]]: i32, %[[VAL_55:.*]]: i32, %[[VAL_56:.*]]: i32):
// CHECK: %[[VAL_57:.*]] = ibis.sblock.isolated (%[[VAL_58:.*]] : i32 = %[[VAL_56]], %[[VAL_59:.*]] : i32 = %[[VAL_54]]) -> i32 {
// CHECK: %[[VAL_57:.*]] = kanagawa.sblock.isolated (%[[VAL_58:.*]] : i32 = %[[VAL_56]], %[[VAL_59:.*]] : i32 = %[[VAL_54]]) -> i32 {
// CHECK: %[[VAL_60:.*]] = arith.addi %[[VAL_58]], %[[VAL_59]] : i32
// CHECK: ibis.sblock.return %[[VAL_60]] : i32
// CHECK: kanagawa.sblock.return %[[VAL_60]] : i32
// CHECK: }
// CHECK: cf.br ^bb1(%[[VAL_57]], %[[VAL_51]], %[[VAL_52]], %[[VAL_53]], %[[VAL_54]], %[[VAL_55]] : i32, i32, i32, i32, i32, i32)
// CHECK: ^bb6(%[[VAL_61:.*]]: i32):
// CHECK: ibis.return %[[VAL_61]] : i32
// CHECK: kanagawa.return %[[VAL_61]] : i32
// CHECK: }
// CHECK: }
ibis.design @foo {
ibis.class sym @ToHandshake {
%this = ibis.this <@foo::@ToHandshake>
ibis.method @foo(%a: i32, %b: i32, %c: i1) -> i32 {
kanagawa.design @foo {
kanagawa.class sym @ToHandshake {
%this = kanagawa.this <@foo::@ToHandshake>
kanagawa.method @foo(%a: i32, %b: i32, %c: i1) -> i32 {
%c2_i32 = arith.constant 2 : i32
%c1 = arith.constant 1 : i32
%c0_i32 = arith.constant 0 : i32
@ -78,7 +78,7 @@ ibis.class sym @ToHandshake {
cf.br ^bb1(%9 : i32)
^bb7: // pred: ^bb1
%10 = memref.load %alloca[] : memref<i32>
ibis.return %10 : i32
kanagawa.return %10 : i32
}
}
}

View File

@ -0,0 +1,79 @@
// XFAIL: *
// See https://github.com/llvm/circt/issues/6658
// RUN: kanagawatool %s --lo --post-kanagawa-ir | FileCheck %s --check-prefix=CHECK-POST-KANAGAWA
// RUN: kanagawatool %s --lo --ir | FileCheck %s --check-prefix=CHECK-IR
// RUN: kanagawatool %s --lo --verilog | FileCheck %s --check-prefix=CHECK-VERILOG
// CHECK-POST-KANAGAWA-LABEL: hw.module @A_B(
// CHECK-POST-KANAGAWA-SAME: in %[[VAL_0:.*]] : !seq.clock, in %[[VAL_1:.*]] : i1, out p_out : i1) {
// CHECK-POST-KANAGAWA: %[[VAL_2:.*]] = seq.compreg %[[VAL_1]], %[[VAL_0]] : i1
// CHECK-POST-KANAGAWA: hw.output %[[VAL_2]] : i1
// CHECK-POST-KANAGAWA: }
// CHECK-POST-KANAGAWA-LABEL: hw.module @A(
// CHECK-POST-KANAGAWA-SAME: in %[[VAL_0:.*]] : i1, in %[[VAL_1:.*]] : !seq.clock, out out : i1) {
// CHECK-POST-KANAGAWA: %[[VAL_2:.*]] = hw.instance "A_B" @A_B(p_clk: %[[VAL_1]]: !seq.clock, p_in: %[[VAL_0]]: i1) -> (p_out: i1)
// CHECK-POST-KANAGAWA: hw.output %[[VAL_2]] : i1
// CHECK-POST-KANAGAWA: }
// CHECK-IR-LABEL: hw.module @A_B(
// CHECK-IR-SAME: in %[[VAL_0:.*]] : i1, in %[[VAL_1:.*]] : i1, out p_out : i1) {
// CHECK-IR: %[[VAL_2:.*]] = sv.reg : !hw.inout<i1>
// CHECK-IR: %[[VAL_3:.*]] = sv.read_inout %[[VAL_2]] : !hw.inout<i1>
// CHECK-IR: sv.alwaysff(posedge %[[VAL_0]]) {
// CHECK-IR: sv.passign %[[VAL_2]], %[[VAL_1]] : i1
// CHECK-IR: }
// CHECK-IR: hw.output %[[VAL_3]] : i1
// CHECK-IR: }
// CHECK-IR-LABEL: hw.module @A(
// CHECK-IR-SAME: in %[[VAL_0:.*]] : i1, in %[[VAL_1:.*]] : i1, out out : i1) {
// CHECK-IR: %[[VAL_2:.*]] = hw.instance "A_B" @A_B(p_clk: %[[VAL_1]]: i1, p_in: %[[VAL_0]]: i1) -> (p_out: i1)
// CHECK-IR: hw.output %[[VAL_2]] : i1
// CHECK-IR: }
// CHECK-VERILOG-LABEL: module A_B(
// CHECK-VERILOG: input p_clk,
// CHECK-VERILOG: p_in,
// CHECK-VERILOG: output p_out
// CHECK-VERILOG: );
// CHECK-VERILOG: reg r;
// CHECK-VERILOG: always_ff @(posedge p_clk)
// CHECK-VERILOG: r <= p_in;
// CHECK-VERILOG: assign p_out = r;
// CHECK-VERILOG: endmodule
// CHECK-VERILOG-LABEL: module A(
// CHECK-VERILOG: input in,
// CHECK-VERILOG: clk,
// CHECK-VERILOG: output out
// CHECK-VERILOG: );
// CHECK-VERILOG: A_B A_B (
// CHECK-VERILOG: .p_clk (clk),
// CHECK-VERILOG: .p_in (in),
// CHECK-VERILOG: .p_out (out)
// CHECK-VERILOG: );
// CHECK-VERILOG: endmodule
kanagawa.design @foo {
kanagawa.class sym @A {
%this = kanagawa.this @A
kanagawa.port.input "in" sym @in : i1
kanagawa.port.output "out" sym @out : i1
kanagawa.port.input "clk" sym @clk : !seq.clock
kanagawa.container@B {
%B_this = kanagawa.this @B
%parent = kanagawa.path [
#kanagawa.step<parent : !kanagawa.scoperef<@foo::@A>>
]
%a_in = kanagawa.get_port %parent, @in : !kanagawa.scoperef<@foo::@A> -> !kanagawa.portref<out i1>
%a_clk = kanagawa.get_port %parent, @clk : !kanagawa.scoperef<@foo::@A> -> !kanagawa.portref<out !seq.clock>
%a_out = kanagawa.get_port %parent, @out : !kanagawa.scoperef<@foo::@A> -> !kanagawa.portref<in i1>
%in = kanagawa.port.read %a_in : !kanagawa.portref<out i1>
%clk = kanagawa.port.read %a_clk : !kanagawa.portref<out !seq.clock>
%r = seq.compreg %in, %clk: i1
kanagawa.port.write %a_out, %r : !kanagawa.portref<in i1>
}
}
}

View File

@ -61,7 +61,7 @@ tools = [
'arcilator', 'circt-as', 'circt-capi-ir-test', 'circt-capi-om-test',
'circt-capi-firrtl-test', 'circt-capi-firtool-test', 'circt-dis',
'circt-lec', 'circt-reduce', 'circt-synth', 'circt-test', 'circt-translate',
'firtool', 'hlstool', 'om-linker', 'ibistool'
'firtool', 'hlstool', 'om-linker', 'kanagawatool'
]
if "CIRCT_OPT_CHECK_IR_ROUNDTRIP" in os.environ:

View File

@ -14,7 +14,7 @@ add_subdirectory(circt-translate)
add_subdirectory(firtool)
add_subdirectory(handshake-runner)
add_subdirectory(hlstool)
add_subdirectory(ibistool)
add_subdirectory(kanagawatool)
add_subdirectory(om-linker)
add_subdirectory(py-split-input-file)

View File

@ -2,11 +2,11 @@ set(LLVM_LINK_COMPONENTS
Support
)
add_circt_tool(ibistool
ibistool.cpp
add_circt_tool(kanagawatool
kanagawatool.cpp
)
llvm_update_compile_flags(ibistool)
target_link_libraries(ibistool
llvm_update_compile_flags(kanagawatool)
target_link_libraries(kanagawatool
PRIVATE
CIRCTExportChiselInterface
@ -22,8 +22,8 @@ target_link_libraries(ibistool
CIRCTCFToHandshake
CIRCTSV
CIRCTSVTransforms
CIRCTIbis
CIRCTIbisTransforms
CIRCTKanagawa
CIRCTKanagawaTransforms
CIRCTTransforms
CIRCTPipelineOps
CIRCTPipelineToHW

View File

@ -1,4 +1,4 @@
//===- ibistool.cpp - The ibistool utility for working with the Ibis dialect =//
//===- kanagawatool.cpp - utility for working with the Kanagawa dialect ---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
//
// This file implements 'ibistool', which composes together a variety of
// CIRCT libraries that can be used to realise an Ibis-based lowering flow.
// This file implements 'kanagawatool', which composes together a variety of
// CIRCT libraries that can be used to realise an Kanagawa-based lowering flow.
//
//===----------------------------------------------------------------------===//
@ -44,10 +44,10 @@
#include "circt/Dialect/DC/DCPasses.h"
#include "circt/Dialect/ESI/ESIDialect.h"
#include "circt/Dialect/ESI/ESIPasses.h"
#include "circt/Dialect/Ibis/IbisDialect.h"
#include "circt/Dialect/Ibis/IbisOps.h"
#include "circt/Dialect/Ibis/IbisPassPipelines.h"
#include "circt/Dialect/Ibis/IbisPasses.h"
#include "circt/Dialect/Kanagawa/KanagawaDialect.h"
#include "circt/Dialect/Kanagawa/KanagawaOps.h"
#include "circt/Dialect/Kanagawa/KanagawaPassPipelines.h"
#include "circt/Dialect/Kanagawa/KanagawaPasses.h"
#include "circt/Dialect/Pipeline/PipelineDialect.h"
#include "circt/Dialect/Pipeline/PipelinePasses.h"
#include "circt/Dialect/SV/SVDialect.h"
@ -62,13 +62,13 @@
using namespace llvm;
using namespace mlir;
using namespace circt;
using namespace ibis;
using namespace kanagawa;
// --------------------------------------------------------------------------
// Tool options
// --------------------------------------------------------------------------
static cl::OptionCategory mainCategory("ibistool Options");
static cl::OptionCategory mainCategory("kanagawatool Options");
static cl::opt<std::string> inputFilename(cl::Positional,
cl::desc("<input file>"),
@ -107,7 +107,7 @@ static cl::opt<bool>
cl::cat(mainCategory));
enum OutputFormatKind {
OutputLoweredIbis,
OutputLoweredKanagawa,
OutputIR,
OutputVerilog,
OutputSplitVerilog
@ -116,8 +116,8 @@ enum OutputFormatKind {
static cl::opt<OutputFormatKind> outputFormat(
cl::desc("Specify output format:"),
cl::values(
clEnumValN(OutputLoweredIbis, "post-ibis-ir",
"Emit IR after Ibis constructs have been lowered away"),
clEnumValN(OutputLoweredKanagawa, "post-kanagawa-ir",
"Emit IR after Kanagawa constructs have been lowered away"),
clEnumValN(OutputIR, "ir", "Emit pre-emission IR"),
clEnumValN(OutputVerilog, "verilog", "Emit Verilog"),
clEnumValN(OutputSplitVerilog, "split-verilog",
@ -130,12 +130,12 @@ static cl::opt<bool>
cl::desc("Add tracing to an iverilog simulated module"),
cl::init(false), cl::cat(mainCategory));
enum FlowKind { HiIbis, LoIbis };
static cl::opt<FlowKind>
flowKind(cl::desc("Specify flow kind:"),
cl::values(clEnumValN(HiIbis, "hi", "High-level Ibis flow"),
clEnumValN(LoIbis, "lo", "Low-level Ibis flow")),
cl::Required, cl::cat(mainCategory));
enum FlowKind { HiKanagawa, LoKanagawa };
static cl::opt<FlowKind> flowKind(
cl::desc("Specify flow kind:"),
cl::values(clEnumValN(HiKanagawa, "hi", "High-level Kanagawa flow"),
clEnumValN(LoKanagawa, "lo", "Low-level Kanagawa flow")),
cl::Required, cl::cat(mainCategory));
static LoweringOptionsOption loweringOptions(mainCategory);
@ -162,8 +162,8 @@ static void loadHandshakeTransformsPipeline(OpPassManager &pm) {
pm.addPass(circt::createInsertMergeBlocksPass());
// Perform dataflow conversion
pm.nest<ibis::DesignOp>().nest<ibis::ClassOp>().addPass(
ibis::createConvertCFToHandshakePass());
pm.nest<kanagawa::DesignOp>().nest<kanagawa::ClassOp>().addPass(
kanagawa::createConvertCFToHandshakePass());
// Canonicalize - necessary after handshake conversion to clean up a lot of
// stuff e.g. simple branches.
pm.addPass(createSimpleCanonicalizerPass());
@ -172,11 +172,13 @@ static void loadHandshakeTransformsPipeline(OpPassManager &pm) {
}
static void loadDCTransformsPipeline(OpPassManager &pm) {
pm.nest<ibis::DesignOp>().nest<ClassOp>().addPass(
ibis::createConvertHandshakeToDCPass());
pm.nest<kanagawa::DesignOp>().nest<ClassOp>().addPass(
kanagawa::createConvertHandshakeToDCPass());
pm.addPass(createSimpleCanonicalizerPass());
pm.nest<ibis::DesignOp>().nest<ClassOp>().nest<DataflowMethodOp>().addPass(
dc::createDCMaterializeForksSinksPass());
pm.nest<kanagawa::DesignOp>()
.nest<ClassOp>()
.nest<DataflowMethodOp>()
.addPass(dc::createDCMaterializeForksSinksPass());
// pm.nest<ClassOp>().addPass(circt::createDCToHWPass());
}
@ -205,27 +207,27 @@ static void loadHWLoweringPipeline(OpPassManager &pm) {
static void loadSchedulingPipeline(OpPassManager &pm) {
// Inject operator library
pm.addPass(ibis::createAddOperatorLibraryPass());
pm.addPass(kanagawa::createAddOperatorLibraryPass());
// Map any arith operators to comb
pm.nest<ibis::DesignOp>()
.nest<ibis::ClassOp>()
.nest<ibis::DataflowMethodOp>()
.nest<ibis::IsolatedStaticBlockOp>()
pm.nest<kanagawa::DesignOp>()
.nest<kanagawa::ClassOp>()
.nest<kanagawa::DataflowMethodOp>()
.nest<kanagawa::IsolatedStaticBlockOp>()
.addPass(circt::createMapArithToCombPass());
// Prepare for scheduling
pm.nest<ibis::DesignOp>()
.nest<ibis::ClassOp>()
.nest<ibis::DataflowMethodOp>()
.nest<ibis::IsolatedStaticBlockOp>()
.addPass(ibis::createPrepareSchedulingPass());
pm.nest<kanagawa::DesignOp>()
.nest<kanagawa::ClassOp>()
.nest<kanagawa::DataflowMethodOp>()
.nest<kanagawa::IsolatedStaticBlockOp>()
.addPass(kanagawa::createPrepareSchedulingPass());
// Schedule!
pm.nest<ibis::DesignOp>()
.nest<ibis::ClassOp>()
.nest<ibis::DataflowMethodOp>()
.nest<ibis::IsolatedStaticBlockOp>()
pm.nest<kanagawa::DesignOp>()
.nest<kanagawa::ClassOp>()
.nest<kanagawa::DataflowMethodOp>()
.nest<kanagawa::IsolatedStaticBlockOp>()
.addPass(pipeline::createScheduleLinearPipelinePass());
}
@ -256,31 +258,31 @@ static void loadLowLevelPassPipeline(
}
}
static void loadIbisHiFlow(
static void loadKanagawaHiFlow(
PassManager &pm, ModuleOp module,
std::optional<std::unique_ptr<llvm::ToolOutputFile>> &outputFile) {
if (verbosePassExecutions)
llvm::errs() << "[ibistool] Will run high-level Ibis flow\n";
llvm::errs() << "[kanagawatool] Will run high-level Kanagawa flow\n";
loadHighLevelControlflowTransformsPipeline(pm);
loadIbisHighLevelPassPipeline(pm);
if (outputFormat != OutputLoweredIbis) {
loadKanagawaHighLevelPassPipeline(pm);
if (outputFormat != OutputLoweredKanagawa) {
loadHandshakeTransformsPipeline(pm);
loadSchedulingPipeline(pm);
loadDCTransformsPipeline(pm);
if (outputFormat != OutputLoweredIbis)
if (outputFormat != OutputLoweredKanagawa)
loadLowLevelPassPipeline(pm, module, outputFile);
}
}
static void loadIbisLoFlow(
static void loadKanagawaLoFlow(
PassManager &pm, ModuleOp module,
std::optional<std::unique_ptr<llvm::ToolOutputFile>> &outputFile) {
if (verbosePassExecutions)
llvm::errs() << "[ibistool] Will run low-level Ibis flow\n";
loadIbisLowLevelPassPipeline(pm);
llvm::errs() << "[kanagawatool] Will run low-level Kanagawa flow\n";
loadKanagawaLowLevelPassPipeline(pm);
if (outputFormat != OutputLoweredIbis)
if (outputFormat != OutputLoweredKanagawa)
loadLowLevelPassPipeline(pm, module, outputFile);
}
@ -292,7 +294,7 @@ static LogicalResult processBuffer(
mlir::OwningOpRef<mlir::ModuleOp> module;
llvm::sys::TimePoint<> parseStartTime;
if (verbosePassExecutions) {
llvm::errs() << "[ibistool] Running MLIR parser\n";
llvm::errs() << "[kanagawatool] Running MLIR parser\n";
parseStartTime = llvm::sys::TimePoint<>::clock::now();
}
auto parserTimer = ts.nest("MLIR Parser");
@ -305,8 +307,8 @@ static LogicalResult processBuffer(
auto elpased = std::chrono::duration<double>(
llvm::sys::TimePoint<>::clock::now() - parseStartTime) /
std::chrono::seconds(1);
llvm::errs() << "[ibistool] -- Done in " << llvm::format("%.3f", elpased)
<< " sec\n";
llvm::errs() << "[kanagawatool] -- Done in "
<< llvm::format("%.3f", elpased) << " sec\n";
}
// Apply any pass manager command line options.
@ -317,10 +319,10 @@ static LogicalResult processBuffer(
return failure();
pm.addPass(createSimpleCanonicalizerPass());
if (flowKind == HiIbis)
loadIbisHiFlow(pm, module.get(), outputFile);
else if (flowKind == LoIbis)
loadIbisLoFlow(pm, module.get(), outputFile);
if (flowKind == HiKanagawa)
loadKanagawaHiFlow(pm, module.get(), outputFile);
else if (flowKind == LoKanagawa)
loadKanagawaLoFlow(pm, module.get(), outputFile);
// Go execute!
if (failed(pm.run(module.get())))
@ -374,7 +376,7 @@ processInput(MLIRContext &context, TimingScope &ts,
llvm::outs());
}
static LogicalResult executeIbistool(MLIRContext &context) {
static LogicalResult executeKanagawatool(MLIRContext &context) {
if (allowUnregisteredDialects)
context.allowUnregisteredDialects();
@ -411,10 +413,11 @@ static LogicalResult executeIbistool(MLIRContext &context) {
return success();
}
/// Main driver for ibistool command. This sets up LLVM and MLIR, and parses
/// command line options before passing off to 'executeIbistool'. This is set
/// up so we can `exit(0)` at the end of the program to avoid teardown of the
/// MLIRContext and modules inside of it (reducing compile time).
/// Main driver for kanagawatool command. This sets up LLVM and MLIR, and
/// parses command line options before passing off to 'executeKanagawatool'.
/// This is set up so we can `exit(0)` at the end of the program to avoid
/// teardown of the MLIRContext and modules inside of it (reducing compile
/// time).
int main(int argc, char **argv) {
InitLLVM y(argc, argv);
@ -433,7 +436,7 @@ int main(int argc, char **argv) {
registerAsmPrinterCLOptions();
// Parse pass names in main to ensure static initialization completed.
cl::ParseCommandLineOptions(argc, argv, "CIRCT Ibis tool\n");
cl::ParseCommandLineOptions(argc, argv, "CIRCT Kanagawa tool\n");
DialectRegistry registry;
// Register MLIR dialects.
@ -450,13 +453,14 @@ int main(int argc, char **argv) {
mlir::registerCanonicalizerPass();
// Register CIRCT dialects.
registry.insert<hw::HWDialect, comb::CombDialect, seq::SeqDialect,
sv::SVDialect, handshake::HandshakeDialect, ibis::IbisDialect,
dc::DCDialect, esi::ESIDialect, pipeline::PipelineDialect>();
registry
.insert<hw::HWDialect, comb::CombDialect, seq::SeqDialect, sv::SVDialect,
handshake::HandshakeDialect, kanagawa::KanagawaDialect,
dc::DCDialect, esi::ESIDialect, pipeline::PipelineDialect>();
// Do the guts of the ibistool process.
// Do the guts of the kanagawatool process.
MLIRContext context(registry);
auto result = executeIbistool(context);
auto result = executeKanagawatool(context);
// Use "exit" instead of return'ing to signal completion. This avoids
// invoking the MLIRContext destructor, which spends a bunch of time