CIRCT  20.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 
18 using namespace circt;
19 using namespace firrtl;
20 
21 /// Consume SourceAnnotation and SinkAnnotation, storing into state
22 LogicalResult circt::firrtl::applyWiring(const AnnoPathValue &target,
23  DictionaryAttr anno,
24  ApplyState &state) {
25  auto clazz = anno.getAs<StringAttr>("class").getValue();
26  auto *context = anno.getContext();
27  ImplicitLocOpBuilder builder(target.ref.getOp()->getLoc(), context);
28 
29  // Convert target to Value
30  Value targetValue;
31  if (auto portTarget = dyn_cast<PortAnnoTarget>(target.ref)) {
32  auto portNum = portTarget.getImpl().getPortNo();
33  if (auto module = dyn_cast<FModuleOp>(portTarget.getOp())) {
34  if (clazz == wiringSourceAnnoClass) {
35  builder.setInsertionPointToStart(module.getBodyBlock());
36  } else if (clazz == wiringSinkAnnoClass) {
37  builder.setInsertionPointToEnd(module.getBodyBlock());
38  }
39  targetValue = getValueByFieldID(builder, module.getArgument(portNum),
40  target.fieldIdx);
41  } else if (auto ext = dyn_cast<FExtModuleOp>(portTarget.getOp())) {
42  InstanceOp inst;
43  if (target.instances.empty()) {
44  auto paths = state.instancePathCache.getAbsolutePaths(ext);
45  if (paths.size() > 1) {
46  mlir::emitError(state.circuit.getLoc())
47  << "cannot resolve a unique instance path from the "
48  "external module target "
49  << target.ref;
50  return failure();
51  }
52  inst = cast<InstanceOp>(paths[0].leaf());
53  } else {
54  inst = cast<InstanceOp>(target.instances.back());
55  }
56  state.wiringProblemInstRefs.insert(inst);
57  builder.setInsertionPointAfter(inst);
58  targetValue =
59  getValueByFieldID(builder, inst->getResult(portNum), target.fieldIdx);
60  } else {
61  return mlir::emitError(state.circuit.getLoc())
62  << "Annotation has invalid target: " << anno;
63  }
64  } else if (auto opResult = dyn_cast<OpAnnoTarget>(target.ref)) {
65  if (target.isOpOfType<WireOp, RegOp, RegResetOp>()) {
66  auto *targetBase = opResult.getOp();
67  builder.setInsertionPointAfter(targetBase);
68  targetValue =
69  getValueByFieldID(builder, targetBase->getResult(0), target.fieldIdx);
70  } else {
71  return mlir::emitError(state.circuit.getLoc())
72  << "Annotation targets non-wireable operation: " << anno;
73  }
74  } else {
75  return mlir::emitError(state.circuit.getLoc())
76  << "Annotation has invalid target: " << anno;
77  }
78 
79  // Get pin field
80  auto pin = anno.getAs<StringAttr>("pin");
81  if (!pin) {
82  return mlir::emitError(state.circuit.getLoc())
83  << "Annotation does not have an associated pin name: " << anno;
84  }
85 
86  // Handle difference between sinks and sources
87  if (clazz == wiringSourceAnnoClass) {
88  if (state.legacyWiringProblems.find(pin) !=
89  state.legacyWiringProblems.end()) {
90  // Check if existing problem can be updated
91  if (state.legacyWiringProblems[pin].source) {
92  return mlir::emitError(state.circuit.getLoc())
93  << "More than one " << wiringSourceAnnoClass
94  << " defined for pin " << pin;
95  }
96  }
97  state.legacyWiringProblems[pin].source = targetValue;
98  } else if (clazz == wiringSinkAnnoClass) {
99  state.legacyWiringProblems[pin].sinks.push_back(targetValue);
100  }
101 
102  return success();
103 }
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
ArrayRef< InstancePath > getAbsolutePaths(ModuleOpInterface op)