CIRCT  19.0.0git
LegacyWiring.cpp
Go to the documentation of this file.
1 //===- LegacyWiring- legacy Wiring annotation resolver --------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the legacy Wiring annotation resolver.
10 //
11 //===----------------------------------------------------------------------===//
12 
17 #include "mlir/IR/ImplicitLocOpBuilder.h"
18 #include "mlir/Support/LogicalResult.h"
19 
20 using namespace circt;
21 using namespace firrtl;
22 
23 /// Consume SourceAnnotation and SinkAnnotation, storing into state
24 LogicalResult circt::firrtl::applyWiring(const AnnoPathValue &target,
25  DictionaryAttr anno,
26  ApplyState &state) {
27  auto clazz = anno.getAs<StringAttr>("class").getValue();
28  auto *context = anno.getContext();
29  ImplicitLocOpBuilder builder(target.ref.getOp()->getLoc(), context);
30 
31  // Convert target to Value
32  Value targetValue;
33  if (auto portTarget = target.ref.dyn_cast<PortAnnoTarget>()) {
34  auto portNum = portTarget.getImpl().getPortNo();
35  if (auto module = dyn_cast<FModuleOp>(portTarget.getOp())) {
36  if (clazz == wiringSourceAnnoClass) {
37  builder.setInsertionPointToStart(module.getBodyBlock());
38  } else if (clazz == wiringSinkAnnoClass) {
39  builder.setInsertionPointToEnd(module.getBodyBlock());
40  }
41  targetValue = getValueByFieldID(builder, module.getArgument(portNum),
42  target.fieldIdx);
43  } else if (auto ext = dyn_cast<FExtModuleOp>(portTarget.getOp())) {
44  InstanceOp inst;
45  if (target.instances.empty()) {
46  auto paths = state.instancePathCache.getAbsolutePaths(ext);
47  if (paths.size() > 1) {
48  mlir::emitError(state.circuit.getLoc())
49  << "cannot resolve a unique instance path from the "
50  "external module target "
51  << target.ref;
52  return failure();
53  }
54  inst = cast<InstanceOp>(paths[0].leaf());
55  } else {
56  inst = cast<InstanceOp>(target.instances.back());
57  }
58  state.wiringProblemInstRefs.insert(inst);
59  builder.setInsertionPointAfter(inst);
60  targetValue =
61  getValueByFieldID(builder, inst->getResult(portNum), target.fieldIdx);
62  } else {
63  return mlir::emitError(state.circuit.getLoc())
64  << "Annotation has invalid target: " << anno;
65  }
66  } else if (auto opResult = target.ref.dyn_cast<OpAnnoTarget>()) {
67  if (target.isOpOfType<WireOp, RegOp, RegResetOp>()) {
68  auto *targetBase = opResult.getOp();
69  builder.setInsertionPointAfter(targetBase);
70  targetValue =
71  getValueByFieldID(builder, targetBase->getResult(0), target.fieldIdx);
72  } else {
73  return mlir::emitError(state.circuit.getLoc())
74  << "Annotation targets non-wireable operation: " << anno;
75  }
76  } else {
77  return mlir::emitError(state.circuit.getLoc())
78  << "Annotation has invalid target: " << anno;
79  }
80 
81  // Get pin field
82  auto pin = anno.getAs<StringAttr>("pin");
83  if (!pin) {
84  return mlir::emitError(state.circuit.getLoc())
85  << "Annotation does not have an associated pin name: " << anno;
86  }
87 
88  // Handle difference between sinks and sources
89  if (clazz == wiringSourceAnnoClass) {
90  if (state.legacyWiringProblems.find(pin) !=
91  state.legacyWiringProblems.end()) {
92  // Check if existing problem can be updated
93  if (state.legacyWiringProblems[pin].source) {
94  return mlir::emitError(state.circuit.getLoc())
95  << "More than one " << wiringSourceAnnoClass
96  << " defined for pin " << pin;
97  }
98  }
99  state.legacyWiringProblems[pin].source = targetValue;
100  } else if (clazz == wiringSinkAnnoClass) {
101  state.legacyWiringProblems[pin].sinks.push_back(targetValue);
102  }
103 
104  return success();
105 }
Builder builder
constexpr const char * wiringSinkAnnoClass
constexpr const char * wiringSourceAnnoClass
LogicalResult applyWiring(const AnnoPathValue &target, DictionaryAttr anno, ApplyState &state)
Consume SourceAnnotation and SinkAnnotation, storing into state.
Value getValueByFieldID(ImplicitLocOpBuilder builder, Value value, unsigned fieldID)
This gets the value targeted by a field id.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
SmallVector< InstanceOp > instances
Operation * getOp() const
State threaded through functions for resolving and applying annotations.
DenseSet< InstanceOp > wiringProblemInstRefs
DenseMap< StringAttr, LegacyWiringProblem > legacyWiringProblems
InstancePathCache & instancePathCache
This represents an annotation targeting a specific operation.
This represents an annotation targeting a specific port of a module, memory, or instance.
ArrayRef< InstancePath > getAbsolutePaths(ModuleOpInterface op)