19 #include "mlir/Pass/Pass.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/Mutex.h"
23 #define DEBUG_TYPE "firrtl-lower-layers"
27 #define GEN_PASS_DEF_LOWERLAYERS
28 #include "circt/Dialect/FIRRTL/Passes.h.inc"
32 using namespace circt;
33 using namespace firrtl;
38 enum class ConnectKind {
53 enum class Delimiter { BindModule =
'_', BindFile =
'-', InlineMacro =
'$' };
61 DenseMap<hw::InnerRefAttr, std::pair<hw::InnerSymAttr, StringAttr>>;
67 static void appendName(StringRef name, SmallString<32> &output,
69 Delimiter delimiter = Delimiter::BindFile) {
73 output.push_back(
static_cast<char>(delimiter));
77 auto i = output.size() - name.size();
78 output[i] = llvm::toLower(output[i]);
81 static void appendName(SymbolRefAttr name, SmallString<32> &output,
83 Delimiter delimiter = Delimiter::BindFile) {
84 appendName(name.getRootReference(), output, toLower, delimiter);
85 for (
auto nested : name.getNestedReferences())
86 appendName(nested.getValue(), output, toLower, delimiter);
92 SymbolRefAttr layerName) {
93 SmallString<32> result;
95 Delimiter::BindModule);
97 Delimiter::BindModule);
104 SmallString<32> result;
106 Delimiter::BindModule);
113 SymbolRefAttr layerName) {
114 SmallString<32> result;
115 result.append(
"layers");
118 result.append(
".sv");
123 static SmallString<32>
125 ArrayRef<FlatSymbolRefAttr> layerName) {
126 SmallString<32> result(
"layer_");
127 result.append(circuitName);
128 for (
auto part : layerName)
130 Delimiter::InlineMacro);
141 auto layer = symbolToLayer.lookup(layerName);
144 return layer->getAttrOfType<hw::OutputFileAttr>(
"output_file");
148 SymbolRefAttr layerName) {
150 return hw::OutputFileAttr::getFromDirectoryAndFilename(
151 &getContext(), file.getDirectory(),
154 return hw::OutputFileAttr::getFromFilename(
161 FModuleOp buildNewModule(OpBuilder &builder, LayerBlockOp layerBlock,
162 SmallVectorImpl<PortInfo> &ports);
165 FailureOr<InnerRefMap> runOnModuleLike(FModuleLike moduleLike);
168 LogicalResult runOnModuleBody(FModuleOp moduleOp,
InnerRefMap &innerRefMap);
172 void removeLayersFromPorts(FModuleLike moduleLike);
175 void removeLayersFromValue(Value value);
179 void removeLayersFromRefCast(RefCastOp cast);
182 void lowerInlineLayerBlock(LayerOp layer, LayerBlockOp layerBlock);
187 StringRef circuitName,
188 SmallVector<FlatSymbolRefAttr> &stack);
190 StringRef circuitName);
193 void runOnOperation()
override;
213 LayerBlockOp layerBlock,
214 SmallVectorImpl<PortInfo> &ports) {
215 auto location = layerBlock.getLoc();
216 auto namehint = moduleNames.lookup(layerBlock);
217 llvm::sys::SmartScopedLock<true> instrumentationLock(*circuitMutex);
218 FModuleOp newModule = builder.create<FModuleOp>(
219 location, builder.getStringAttr(namehint),
222 if (
auto dir =
getOutputFile(layerBlock.getLayerNameAttr())) {
223 assert(dir.isDirectory());
224 newModule->setAttr(
"output_file", dir);
226 SymbolTable::setSymbolVisibility(newModule, SymbolTable::Visibility::Private);
231 auto type = dyn_cast<RefType>(value.getType());
232 if (!type || !type.getLayer())
234 value.setType(type.removeLayer());
238 auto result = cast.getResult();
239 auto oldType = result.getType();
240 if (oldType.getLayer()) {
241 auto input = cast.getInput();
242 auto srcType = input.getType();
243 auto newType = oldType.removeLayer();
244 if (newType == srcType) {
245 result.replaceAllUsesWith(input);
249 result.setType(newType);
254 auto oldTypeAttrs = moduleLike.getPortTypesAttr();
255 SmallVector<Attribute> newTypeAttrs;
256 newTypeAttrs.reserve(oldTypeAttrs.size());
257 bool changed =
false;
259 for (
auto typeAttr : oldTypeAttrs.getAsRange<TypeAttr>()) {
260 if (
auto refType = dyn_cast<RefType>(typeAttr.getValue())) {
261 if (refType.getLayer()) {
266 newTypeAttrs.push_back(typeAttr);
272 moduleLike.setPortTypesAttr(
275 if (
auto moduleOp = dyn_cast<FModuleOp>(moduleLike.getOperation())) {
276 for (
auto arg : moduleOp.getBodyBlock()->getArguments())
277 removeLayersFromValue(arg);
281 FailureOr<InnerRefMap>
284 llvm::dbgs() <<
"Module: " << moduleLike.getModuleName() <<
"\n";
285 llvm::dbgs() <<
" Examining Layer Blocks:\n";
291 TypeSwitch<Operation *, LogicalResult>(moduleLike.getOperation())
292 .Case<FModuleOp>([&](
auto op) {
294 removeLayersFromPorts(op);
295 return runOnModuleBody(op, innerRefMap);
297 .Case<FExtModuleOp, FIntModuleOp, FMemModuleOp>([&](
auto op) {
299 removeLayersFromPorts(op);
302 .Case<ClassOp, ExtClassOp>([](
auto) {
return success(); })
304 [](
auto *op) {
return op->emitError(
"unknown module-like op"); });
313 LayerBlockOp layerBlock) {
314 OpBuilder builder(layerBlock);
315 auto macroName = macroNames[layer];
316 auto ifDef = builder.create<
sv::IfDefOp>(layerBlock.getLoc(), macroName);
317 ifDef.getBodyRegion().takeBody(layerBlock.getBodyRegion());
323 CircuitOp circuitOp = moduleOp->getParentOfType<CircuitOp>();
324 StringRef circuitName = circuitOp.getName();
325 hw::InnerSymbolNamespace ns(moduleOp);
330 DenseMap<InstanceOp, FModuleOp> createdInstances;
343 auto result = moduleOp.walk<mlir::WalkOrder::PostOrder>([&](Operation *op) {
345 if (
auto wire = dyn_cast<WireOp>(op)) {
346 removeLayersFromValue(wire.getResult());
347 return WalkResult::advance();
349 if (
auto sub = dyn_cast<RefSubOp>(op)) {
350 removeLayersFromValue(sub.getResult());
351 return WalkResult::advance();
353 if (
auto instance = dyn_cast<InstanceOp>(op)) {
354 instance.setLayers({});
355 for (
auto result : instance.getResults())
356 removeLayersFromValue(result);
357 return WalkResult::advance();
359 if (
auto cast = dyn_cast<RefCastOp>(op)) {
360 removeLayersFromRefCast(cast);
361 return WalkResult::advance();
364 auto layerBlock = dyn_cast<LayerBlockOp>(op);
366 return WalkResult::advance();
368 auto layer = symbolToLayer.lookup(layerBlock.getLayerName());
370 if (layer.getConvention() == LayerConvention::Inline) {
371 lowerInlineLayerBlock(layer, layerBlock);
372 return WalkResult::advance();
375 assert(layer.getConvention() == LayerConvention::Bind);
376 Block *body = layerBlock.getBody(0);
377 OpBuilder builder(moduleOp);
381 SmallVector<PortInfo> ports;
384 SmallVector<ConnectInfo> connectValues;
387 auto createInputPort = [&](Value operand, Location loc) {
393 auto type = operand.getType();
394 if (
auto refType = dyn_cast<RefType>(type))
395 type = refType.getType();
397 ports.push_back({builder.getStringAttr(portName), type,
Direction::In,
403 Value replacement = body->addArgument(type, loc);
404 if (isa<RefType>(operand.getType())) {
405 OpBuilder::InsertionGuard guard(builder);
406 builder.setInsertionPointToStart(body);
407 replacement = builder.create<RefSendOp>(loc, replacement);
409 operand.replaceUsesWithIf(replacement, [&](OpOperand &use) {
410 auto *user = use.getOwner();
411 if (!layerBlock->isAncestor(user))
413 if (
auto connectLike = dyn_cast<FConnectLike>(user)) {
414 if (use.getOperandNumber() == 0)
420 connectValues.push_back({operand, ConnectKind::NonRef});
426 auto getPortLoc = [&](Value port) -> Location {
428 if (
auto *destOp = port.getDefiningOp())
429 if (
auto instOp = dyn_cast<InstanceOp>(destOp)) {
430 auto modOpIt = createdInstances.find(instOp);
431 if (modOpIt != createdInstances.end()) {
432 auto portNum = cast<OpResult>(port).getResultNumber();
433 loc = modOpIt->getSecond().getPortLocation(portNum);
441 auto createOutputPort = [&](Value dest, Value src) {
442 auto loc = getPortLoc(dest);
443 auto portNum = ports.size();
447 if (
auto oldRef = dyn_cast<RefType>(dest.getType()))
451 type_cast<FIRRTLBaseType>(dest.getType()).getPassiveType(),
454 ports.push_back({builder.getStringAttr(portName), refType,
Direction::Out,
456 Value replacement = body->addArgument(refType, loc);
457 if (isa<RefType>(dest.getType())) {
458 dest.replaceUsesWithIf(replacement, [&](OpOperand &use) {
459 auto *user = use.getOwner();
460 if (!layerBlock->isAncestor(user))
462 if (
auto connectLike = dyn_cast<FConnectLike>(user)) {
463 if (use.getOperandNumber() == 0)
468 connectValues.push_back({dest, ConnectKind::Ref});
471 connectValues.push_back({dest, ConnectKind::NonRef});
472 OpBuilder::InsertionGuard guard(builder);
473 builder.setInsertionPointAfterValue(src);
474 builder.create<RefDefineOp>(
475 loc, body->getArgument(portNum),
476 builder.create<RefSendOp>(loc, src)->getResult(0));
479 SmallVector<hw::InnerSymAttr> innerSyms;
480 SmallVector<RWProbeOp> rwprobes;
481 auto layerBlockWalkResult = layerBlock.walk([&](Operation *op) {
484 if (
auto symOp = dyn_cast<hw::InnerSymbolOpInterface>(op))
485 if (
auto innerSym = symOp.getInnerSymAttr())
486 innerSyms.push_back(innerSym);
498 if (
auto instOp = dyn_cast<InstanceOp>(op)) {
500 if (!createdInstances.contains(instOp))
501 return WalkResult::advance();
505 <<
" Found instance created from nested layer block:\n"
506 <<
" module: " << instOp.getModuleName() <<
"\n"
507 <<
" instance: " << instOp.getName() <<
"\n";
509 instOp->moveBefore(layerBlock);
510 return WalkResult::advance();
522 if (isa<SubfieldOp, SubindexOp>(op)) {
523 auto input = op->getOperand(0);
524 if (!firrtl::type_cast<FIRRTLBaseType>(input.getType()).isPassive() &&
526 op->moveBefore(layerBlock);
527 return WalkResult::advance();
530 if (
auto subOp = dyn_cast<SubaccessOp>(op)) {
531 auto input = subOp.getInput();
532 if (firrtl::type_cast<FIRRTLBaseType>(input.getType()).isPassive())
533 return WalkResult::advance();
537 subOp->moveBefore(layerBlock);
538 return WalkResult::advance();
540 auto diag = op->emitOpError()
541 <<
"has a non-passive operand and captures a value defined "
542 "outside its enclosing bind-convention layerblock. The "
543 "'LowerLayers' pass cannot lower this as it would "
544 "create an output port on the resulting module.";
545 diag.attachNote(layerBlock.getLoc())
546 <<
"the layerblock is defined here";
547 return WalkResult::interrupt();
550 if (
auto rwprobe = dyn_cast<RWProbeOp>(op)) {
551 rwprobes.push_back(rwprobe);
552 return WalkResult::advance();
555 if (
auto connect = dyn_cast<FConnectLike>(op)) {
560 if (!srcInLayerBlock && !dstInLayerBlock) {
561 connect->moveBefore(layerBlock);
562 return WalkResult::advance();
565 if (!srcInLayerBlock) {
566 createInputPort(src, op->getLoc());
567 return WalkResult::advance();
570 if (!dstInLayerBlock) {
571 createOutputPort(dst, src);
572 if (!isa<RefType>(dst.getType()))
574 return WalkResult::advance();
577 return WalkResult::advance();
593 if (
auto refResolve = dyn_cast<RefResolveOp>(op))
594 if (refResolve.getResult().hasOneUse() &&
595 refResolve.getRef().getParentBlock() != body)
596 if (
auto connect = dyn_cast<MatchingConnectOp>(
597 *refResolve.getResult().getUsers().begin()))
598 if (
connect.getDest().getParentBlock() != body) {
599 refResolve->moveBefore(layerBlock);
600 return WalkResult::advance();
604 for (
auto operand : op->getOperands()) {
606 createInputPort(operand, op->getLoc());
609 return WalkResult::advance();
612 if (layerBlockWalkResult.wasInterrupted())
613 return WalkResult::interrupt();
616 FModuleOp newModule = buildNewModule(builder, layerBlock, ports);
617 SymbolTable::setSymbolVisibility(newModule,
618 SymbolTable::Visibility::Private);
619 newModule.getBody().takeBody(layerBlock.getRegion());
622 llvm::dbgs() <<
" New Module: " << moduleNames.lookup(layerBlock)
624 llvm::dbgs() <<
" ports:\n";
625 for (
size_t i = 0, e = ports.size(); i != e; ++i) {
626 auto port = ports[i];
627 auto value = connectValues[i];
628 llvm::dbgs() <<
" - name: " << port.getName() <<
"\n"
629 <<
" type: " << port.type <<
"\n"
630 <<
" direction: " << port.direction <<
"\n"
631 <<
" value: " << value.value <<
"\n"
633 << (value.kind == ConnectKind::NonRef ?
"NonRef" :
"Ref")
643 builder.setInsertionPointAfter(layerBlock);
645 auto instanceOp = builder.create<InstanceOp>(
646 layerBlock.getLoc(), newModule,
648 instanceName, NameKindEnum::DroppableName,
649 ArrayRef<Attribute>{},
650 ArrayRef<Attribute>{},
true,
652 (innerSyms.empty() ? hw::InnerSymAttr{}
654 ns.newName(instanceName)))));
657 outputFileForLayer(circuitName, layerBlock.getLayerName());
658 instanceOp->setAttr(
"output_file", outputFile);
660 createdInstances.try_emplace(instanceOp, newModule);
662 LLVM_DEBUG(llvm::dbgs() <<
" moved inner refs:\n");
663 for (hw::InnerSymAttr innerSym : innerSyms) {
665 innerSym.getSymName());
666 auto splice = std::make_pair(instanceOp.getInnerSymAttr(),
667 newModule.getModuleNameAttr());
668 innerRefMap.insert({oldInnerRef, splice});
669 LLVM_DEBUG(llvm::dbgs() <<
" - ref: " << oldInnerRef <<
"\n"
670 <<
" splice: " << splice.first <<
", "
671 << splice.second <<
"\n";);
675 for (
auto rwprobe : rwprobes) {
676 auto targetRef = rwprobe.getTarget();
677 auto mapped = innerRefMap.find(targetRef);
678 if (mapped == innerRefMap.end()) {
679 assert(targetRef.getModule() == moduleOp.getNameAttr());
682 return WalkResult::interrupt();
683 auto target = ist->lookup(targetRef.getName());
688 "rwprobe capture not supported with bind convention layer")
689 .attachNote(fieldref.getLoc())
690 .append(
"rwprobe target outside of bind layer");
691 return WalkResult::interrupt();
694 if (mapped->second.second != newModule.getModuleNameAttr())
695 return rwprobe.emitError(
"rwprobe target refers to different module"),
696 WalkResult::interrupt();
698 rwprobe.setTargetAttr(
703 assert(ports.size() == connectValues.size() &&
704 "the number of instance ports and values to connect to them must be "
706 for (
unsigned portNum = 0, e = newModule.getNumPorts(); portNum < e;
708 OpBuilder::InsertionGuard guard(builder);
709 builder.setInsertionPointAfterValue(instanceOp.getResult(portNum));
711 auto src = connectValues[portNum].value;
712 if (isa<RefType>(src.getType()))
713 src = builder.create<RefResolveOp>(
714 newModule.getPortLocationAttr(portNum), src);
715 builder.create<MatchingConnectOp>(
716 newModule.getPortLocationAttr(portNum),
717 instanceOp.getResult(portNum), src);
718 }
else if (isa<RefType>(instanceOp.getResult(portNum).getType()) &&
719 connectValues[portNum].kind == ConnectKind::Ref)
720 builder.create<RefDefineOp>(getPortLoc(connectValues[portNum].value),
721 connectValues[portNum].value,
722 instanceOp.getResult(portNum));
724 builder.create<MatchingConnectOp>(
725 getPortLoc(connectValues[portNum].value),
726 connectValues[portNum].value,
727 builder.create<RefResolveOp>(newModule.getPortLocationAttr(portNum),
728 instanceOp.getResult(portNum)));
732 return WalkResult::advance();
734 return success(!result.wasInterrupted());
738 LayerOp layer, StringRef circuitName,
739 SmallVector<FlatSymbolRefAttr> &stack) {
741 ArrayRef stackRef(stack);
742 symbolToLayer.insert(
745 if (layer.getConvention() == LayerConvention::Inline) {
746 auto *ctx = &getContext();
748 auto symName = ns.
newName(macName);
751 auto macNameAttr = StringAttr();
752 if (macName != symName)
755 b.create<sv::MacroDeclOp>(layer->getLoc(), symNameAttr, ArrayAttr(),
759 for (
auto child : layer.getOps<LayerOp>())
760 preprocessLayers(ns, b, child, circuitName, stack);
765 StringRef circuitName) {
767 SmallVector<FlatSymbolRefAttr> stack;
768 preprocessLayers(ns, b, layer, circuitName, stack);
775 llvm::dbgs() <<
"==----- Running LowerLayers "
776 "-------------------------------------------------===\n");
777 CircuitOp circuitOp = getOperation();
778 StringRef circuitName = circuitOp.getName();
781 llvm::sys::SmartMutex<true> mutex;
782 circuitMutex = &mutex;
785 for (
auto &op : *circuitOp.getBodyBlock()) {
788 if (
auto moduleOp = dyn_cast<FModuleOp>(op)) {
789 moduleOp->walk([&](LayerBlockOp layerBlockOp) {
791 layerBlockOp.getLayerName());
792 moduleNames.insert({layerBlockOp, ns.
newName(name)});
798 if (
auto layerOp = dyn_cast<LayerOp>(op)) {
799 preprocessLayers(ns, layerOp, circuitName);
804 auto mergeMaps = [](
auto &&a,
auto &&b) {
806 return std::forward<decltype(a)>(a);
808 return std::forward<decltype(b)>(b);
812 return std::forward<decltype(a)>(a);
816 SmallVector<FModuleLike> modules(
817 circuitOp.getBodyBlock()->getOps<FModuleLike>());
819 circuitOp.getContext(), modules, FailureOr<InnerRefMap>(
InnerRefMap{}),
820 mergeMaps, [
this](FModuleLike mod) -> FailureOr<InnerRefMap> {
821 return runOnModuleLike(mod);
823 if (failed(failureOrInnerRefMap))
824 return signalPassFailure();
825 auto &innerRefMap = *failureOrInnerRefMap;
834 for (hw::HierPathOp hierPathOp : circuitOp.getOps<hw::HierPathOp>()) {
835 SmallVector<Attribute> newNamepath;
836 bool modified =
false;
837 for (
auto attr : hierPathOp.getNamepath()) {
838 hw::InnerRefAttr innerRef = dyn_cast<hw::InnerRefAttr>(attr);
840 newNamepath.push_back(attr);
843 auto it = innerRefMap.find(innerRef);
844 if (it == innerRefMap.end()) {
845 newNamepath.push_back(attr);
849 auto &[inst, mod] = it->getSecond();
850 newNamepath.push_back(
856 hierPathOp.setNamepathAttr(
872 OpBuilder builder(circuitOp);
873 SmallVector<std::pair<LayerOp, StringAttr>> layers;
874 circuitOp.walk<mlir::WalkOrder::PreOrder>([&](LayerOp layerOp) {
875 auto parentOp = layerOp->getParentOfType<LayerOp>();
876 while (!layers.empty() && parentOp != layers.back().first)
879 if (layerOp.getConvention() == LayerConvention::Inline) {
880 layers.emplace_back(layerOp,
nullptr);
884 builder.setInsertionPointToStart(circuitOp.getBodyBlock());
888 SmallString<32> prefixFile(
"layers-"), prefixMacro(
"layers_");
889 prefixFile.append(circuitName);
890 prefixFile.append(
"-");
891 prefixMacro.append(circuitName);
892 prefixMacro.append(
"_");
893 for (
auto [layer, _] : layers) {
894 prefixFile.append(layer.getSymName());
895 prefixFile.append(
"-");
896 prefixMacro.append(layer.getSymName());
897 prefixMacro.append(
"_");
899 prefixFile.append(layerOp.getSymName());
900 prefixMacro.append(layerOp.getSymName());
902 SmallString<128> includes;
903 for (
auto [_, strAttr] : layers) {
906 includes.append(strAttr);
907 includes.append(
"\n");
910 hw::OutputFileAttr bindFile;
911 if (
auto outputFile =
912 layerOp->getAttrOfType<hw::OutputFileAttr>(
"output_file")) {
913 auto dir = outputFile.getDirectory();
914 bindFile = hw::OutputFileAttr::getFromDirectoryAndFilename(
915 &getContext(), dir, prefixFile +
".sv",
918 bindFile = hw::OutputFileAttr::getFromFilename(
919 &getContext(), prefixFile +
".sv",
true);
923 auto header = builder.create<sv::VerbatimOp>(
925 includes +
"`ifndef " + prefixMacro +
"\n" +
"`define " + prefixMacro);
926 header->setAttr(
"output_file", bindFile);
929 builder.setInsertionPointToEnd(circuitOp.getBodyBlock());
930 auto footer = builder.create<sv::VerbatimOp>(layerOp.getLoc(),
931 "`endif // " + prefixMacro);
932 footer->setAttr(
"output_file", bindFile);
934 if (!layerOp.getBody().getOps<LayerOp>().
empty())
937 builder.getStringAttr(
"`include \"" +
938 bindFile.getFilename().getValue() +
"\""));
943 llvm::make_early_inc_range(circuitOp.getBodyBlock()->getOps<LayerOp>()))
948 return std::make_unique<LowerLayersPass>();
static OutputFileAttr getOutputFile(igraph::ModuleOpInterface op)
assert(baseType &&"element must be base type")
static InstancePath empty
static SmallString< 32 > instanceNameForLayer(SymbolRefAttr layerName)
For a layerblock @A::@B::@C, the generated instance is called a_b_c.
static SmallString< 32 > macroNameForLayer(StringRef circuitName, ArrayRef< FlatSymbolRefAttr > layerName)
For a layerblock @A::@B::@C, the verilog macro is A_B_C.
static SmallString< 32 > fileNameForLayer(StringRef circuitName, SymbolRefAttr layerName)
For all layerblocks @A::@B::@C in a circuit called Circuit, the output filename is layers-Circuit-A-B...
static SmallString< 32 > moduleNameForLayer(StringRef moduleName, SymbolRefAttr layerName)
For a layer @A::@B::@C in module Module, the generated module is called Module_A_B_C.
static void appendName(StringRef name, SmallString< 32 > &output, bool toLower=false, Delimiter delimiter=Delimiter::BindFile)
DenseMap< hw::InnerRefAttr, std::pair< hw::InnerSymAttr, StringAttr > > InnerRefMap
void runOnOperation() override
Entry point for the function.
void removeLayersFromPorts(FModuleLike moduleLike)
Update the module's port types to remove any explicit layer requirements from any probe types.
FailureOr< InnerRefMap > runOnModuleLike(FModuleLike moduleLike)
Strip layer colors from the module's interface.
DenseMap< LayerOp, FlatSymbolRefAttr > macroNames
A map from inline layers to their macro names.
void lowerInlineLayerBlock(LayerOp layer, LayerBlockOp layerBlock)
Lower an inline layerblock to an ifdef block.
DenseMap< LayerBlockOp, StringRef > moduleNames
A map of layer blocks to module name that should be created for it.
hw::OutputFileAttr outputFileForLayer(StringRef circuitName, SymbolRefAttr layerName)
void removeLayersFromRefCast(RefCastOp cast)
Remove any layers from the result of the cast.
LogicalResult runOnModuleBody(FModuleOp moduleOp, InnerRefMap &innerRefMap)
Extract layerblocks and strip probe colors from all ops under the module.
DenseMap< SymbolRefAttr, LayerOp > symbolToLayer
A mapping of symbol name to layer operation.
FModuleOp buildNewModule(OpBuilder &builder, LayerBlockOp layerBlock, SmallVectorImpl< PortInfo > &ports)
Safely build a new module with a given namehint.
hw::OutputFileAttr getOutputFile(SymbolRefAttr layerName)
void removeLayersFromValue(Value value)
Update the value's type to remove any layers from any probe types.
void preprocessLayers(CircuitNamespace &ns, OpBuilder &b, LayerOp layer, StringRef circuitName, SmallVector< FlatSymbolRefAttr > &stack)
Preprocess layers to build macro declarations and cache information about the layers so that this can...
llvm::sys::SmartMutex< true > * circuitMutex
Indicates exclusive access to modify the circuitNamespace and the circuit.
This class represents a reference to a specific field or element of an aggregate value.
StringRef newName(const Twine &name)
Return a unique name, derived from the input name, and add the new name to the internal namespace.
static FailureOr< InnerSymbolTable > get(Operation *op)
Construct an InnerSymbolTable, checking for verification failure.
def connect(destination, source)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
FieldRef getFieldRefForTarget(const hw::InnerSymTarget &ist)
Get FieldRef pointing to the specified inner symbol target, which must be valid.
std::unique_ptr< mlir::Pass > createLowerLayersPass()
static ResultTy transformReduce(MLIRContext *context, IterTy begin, IterTy end, ResultTy init, ReduceFuncTy reduce, TransformFuncTy transform)
Wrapper for llvm::parallelTransformReduce that performs the transform_reduce serially when MLIR multi...
std::pair< std::string, bool > getFieldName(const FieldRef &fieldRef, bool nameSafe=false)
Get a string identifier representing the FieldRef.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
bool isAncestorOfValueOwner(Operation *op, Value value)
Return true if a Value is created "underneath" an operation.
The namespace of a CircuitOp, generally inhabited by modules.