CIRCT 20.0.0git
Loading...
Searching...
No Matches
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
18using namespace circt;
19using namespace firrtl;
20
21/// Consume SourceAnnotation and SinkAnnotation, storing into state
22LogicalResult 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.
SmallVector< InstanceOp > instances
State threaded through functions for resolving and applying annotations.
DenseSet< InstanceOp > wiringProblemInstRefs
DenseMap< StringAttr, LegacyWiringProblem > legacyWiringProblems
InstancePathCache & instancePathCache
ArrayRef< InstancePath > getAbsolutePaths(ModuleOpInterface op)