9#include "../PassDetails.h" 
   18#include "mlir/Transforms/GreedyPatternRewriteDriver.h" 
   22#define GEN_PASS_DEF_LOWERESIBUNDLES 
   23#include "circt/Dialect/ESI/ESIPasses.h.inc" 
   46                       SmallVectorImpl<Value> &newOperands,
 
   47                       ArrayRef<Backedge> newResults) 
override;
 
   49                        SmallVectorImpl<Value> &newOperands,
 
   50                        ArrayRef<Backedge> newResults) 
override;
 
   57  SmallVector<hw::PortInfo, 4> newInputChannels;
 
   58  SmallVector<hw::PortInfo, 4> newOutputChannels;
 
   64  FailureOr<std::unique_ptr<PortConversion>> build(
hw::PortInfo port)
 override {
 
   65    return llvm::TypeSwitch<Type, FailureOr<std::unique_ptr<PortConversion>>>(
 
   67        .Case([&](esi::ChannelBundleType)
 
   68                  -> FailureOr<std::unique_ptr<PortConversion>> {
 
   69          return {std::make_unique<BundlePort>(converter, port)};
 
   78void BundlePort::mapInputSignals(OpBuilder &b, Operation *inst, Value,
 
   79                                 SmallVectorImpl<Value> &newOperands,
 
   80                                 ArrayRef<Backedge> newResults) {
 
   82  SmallVector<Value, 4> fromChannels(
 
   83      llvm::map_range(newOutputChannels, [&](
hw::PortInfo port) {
 
   84        return newResults[port.
argNum];
 
   86  SmallVector<Type, 5> toChannelTypes(llvm::map_range(
 
   88  auto unpack = UnpackBundleOp::create(
 
   90      inst->getOperand(origPort.argNum), fromChannels);
 
   93  for (
auto [idx, inPort] : 
llvm::enumerate(newInputChannels))
 
   94    newOperands[inPort.argNum] = unpack.getResult(idx);
 
   99void BundlePort::mapOutputSignals(OpBuilder &b, Operation *inst, Value,
 
  100                                  SmallVectorImpl<Value> &newOperands,
 
  101                                  ArrayRef<Backedge> newResults) {
 
  103  SmallVector<Value, 4> toChannels(
 
  104      llvm::map_range(newOutputChannels, [&](
hw::PortInfo port) {
 
  105        return newResults[port.
argNum];
 
  107  SmallVector<Type, 5> fromChannelTypes(llvm::map_range(
 
  109  auto pack = PackBundleOp::create(
 
  110      b, origPort.loc, cast<ChannelBundleType>(origPort.type), toChannels);
 
  113  for (
auto [idx, inPort] : 
llvm::enumerate(newInputChannels))
 
  114    newOperands[inPort.argNum] = pack.getFromChannels()[idx];
 
  116  inst->getResult(origPort.argNum).replaceAllUsesWith(pack.getBundle());
 
  121void BundlePort::buildInputSignals() {
 
  122  auto bundleType = cast<ChannelBundleType>(origPort.type);
 
  123  SmallVector<Value, 4> newInputValues;
 
  124  SmallVector<BundledChannel, 4> outputChannels;
 
  128    if (ch.direction == ChannelDirection::to) {
 
  130      newInputValues.push_back(converter.createNewInput(
 
  131          origPort, 
"_" + ch.name.getValue(), ch.type, newPort));
 
  132      newInputChannels.push_back(newPort);
 
  135      outputChannels.push_back(ch);
 
  143    ImplicitLocOpBuilder b(origPort.loc, body, body->begin());
 
  144    pack = PackBundleOp::create(b, bundleType, newInputValues);
 
  145    body->getArgument(origPort.argNum).replaceAllUsesWith(pack.getBundle());
 
  150  newOutputChannels.resize(outputChannels.size());
 
  151  for (
auto [idx, ch] : 
llvm::enumerate(outputChannels))
 
  152    converter.createNewOutput(origPort, 
"_" + ch.name.getValue(), ch.type,
 
  153                              pack ? pack.getFromChannels()[idx] : nullptr,
 
  154                              newOutputChannels[idx]);
 
  159void BundlePort::buildOutputSignals() {
 
  160  auto bundleType = cast<ChannelBundleType>(origPort.type);
 
  161  SmallVector<Value, 4> unpackChannels;
 
  162  SmallVector<BundledChannel, 4> outputChannels;
 
  164  SmallVector<Type, 4> unpackOpResultTypes;
 
  167    if (ch.direction == ChannelDirection::from) {
 
  169      unpackChannels.push_back(converter.createNewInput(
 
  170          origPort, 
"_" + ch.name.getValue(), ch.type, newPort));
 
  171      newInputChannels.push_back(newPort);
 
  174      unpackOpResultTypes.push_back(ch.type);
 
  175      outputChannels.push_back(ch);
 
  181  UnpackBundleOp unpack;
 
  183    auto builder = OpBuilder::atBlockTerminator(body);
 
  184    unpack = UnpackBundleOp::create(
 
  185        builder, origPort.loc,
 
  186        body->getTerminator()->getOperand(origPort.argNum), unpackChannels);
 
  191  newOutputChannels.resize(outputChannels.size());
 
  192  for (
auto [idx, ch] : 
llvm::enumerate(outputChannels))
 
  193    converter.createNewOutput(origPort, 
"_" + ch.name.getValue(), ch.type,
 
  194                              unpack ? unpack.getToChannels()[idx] : nullptr,
 
  195                              newOutputChannels[idx]);
 
  201    : 
public circt::esi::impl::LowerESIBundlesBase<ESIBundlesPass> {
 
  202  void runOnOperation() 
override;
 
  207void ESIBundlesPass::runOnOperation() {
 
  208  MLIRContext &
ctxt = getContext();
 
  209  ModuleOp top = getOperation();
 
  213      getAnalysis<circt::hw::InstanceGraph>();
 
  214  for (
auto mod : top.getOps<HWMutableModuleLike>()) {
 
  217      return signalPassFailure();
 
  223  PackBundleOp::getCanonicalizationPatterns(
patterns, &ctxt);
 
  224  UnpackBundleOp::getCanonicalizationPatterns(
patterns, &ctxt);
 
  225  if (failed(mlir::applyPatternsGreedily(getOperation(), std::move(
patterns))))
 
  228  top.walk([&](PackBundleOp pack) {
 
  229    pack.emitError(
"PackBundleOp should have been canonicalized away by now");
 
  234std::unique_ptr<OperationPass<ModuleOp>>
 
  236  return std::make_unique<ESIBundlesPass>();
 
 
HW-specific instance graph with a virtual entry node linking to all publicly visible modules.
 
PortConversionBuilder(PortConverterImpl &converter)
 
virtual FailureOr< std::unique_ptr< PortConversion > > build(hw::PortInfo port)
 
Base class for the port conversion of a particular port.
 
virtual void buildInputSignals()=0
 
virtual void mapInputSignals(OpBuilder &b, Operation *inst, Value instValue, SmallVectorImpl< Value > &newOperands, ArrayRef< Backedge > newResults)=0
Update an instance port to the new port information.
 
virtual void mapOutputSignals(OpBuilder &b, Operation *inst, Value instValue, SmallVectorImpl< Value > &newOperands, ArrayRef< Backedge > newResults)=0
 
virtual void buildOutputSignals()=0
 
std::unique_ptr< OperationPass< ModuleOp > > createESIBundleLoweringPass()
 
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
 
int run(Type[Generator] generator=CppGenerator, cmdline_args=sys.argv)
 
This holds the name, type, direction of a module's ports.
 
size_t argNum
This is the argument index or the result index depending on the direction.