mirror of https://github.com/llvm/circt.git
[Ibis] Rename to 'Kanagawa' (#7832)
This commit is contained in:
parent
83b5ff3910
commit
58665c5921
|
@ -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
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
# 'ibis' Dialect
|
||||
|
||||
[include "Dialects/Ibis.md"]
|
|
@ -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.
|
|
@ -0,0 +1,3 @@
|
|||
# 'kanagawa' Dialect
|
||||
|
||||
[include "Dialects/Kanagawa.md"]
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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 ®istry) {
|
|||
hw::HWDialect,
|
||||
hwarith::HWArithDialect,
|
||||
interop::InteropDialect,
|
||||
ibis::IbisDialect,
|
||||
kanagawa::KanagawaDialect,
|
||||
llhd::LLHDDialect,
|
||||
loopschedule::LoopScheduleDialect,
|
||||
ltl::LTLDialect,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -14,7 +14,7 @@ set(CIRCT_INTEGRATION_TEST_DEPENDS
|
|||
circt-test-runners
|
||||
firtool
|
||||
hlstool
|
||||
ibistool
|
||||
kanagawatool
|
||||
handshake-runner
|
||||
)
|
||||
|
||||
|
|
|
@ -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>
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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'
|
||||
]
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -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
|
||||
)
|
|
@ -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)
|
|
@ -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"
|
|
@ -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"
|
|
@ -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"
|
||||
>();
|
||||
}
|
|
@ -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
|
||||
)
|
|
@ -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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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());
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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
2
llvm
|
@ -1 +1 @@
|
|||
Subproject commit 3cc852ece438a63e7b09d1c84a81d21598454e1a
|
||||
Subproject commit 8193832fb988e3df1e8e726634783805dca8d9b6
|
|
@ -33,7 +33,7 @@ set(CIRCT_TEST_DEPENDS
|
|||
handshake-runner
|
||||
firtool
|
||||
hlstool
|
||||
ibistool
|
||||
kanagawatool
|
||||
om-linker
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
}
|
|
@ -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>>
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
}
|
|
@ -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>) -> ()
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>]
|
||||
}
|
||||
}
|
|
@ -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()
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
}
|
|
@ -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>>
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
}
|
|
@ -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>) -> ()
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>]
|
||||
}
|
||||
}
|
|
@ -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()
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue