10#include "slang/ast/Compilation.h"
11#include "slang/ast/symbols/ClassSymbols.h"
12#include "llvm/ADT/ScopeExit.h"
15using namespace ImportVerilog;
22 SmallString<64> &prefix) {
23 if (symbol.kind != slang::ast::SymbolKind::Package)
26 if (!symbol.name.empty()) {
27 prefix += symbol.name;
44 BaseVisitor(
Context &context, Location loc)
45 : context(context), loc(loc), builder(context.builder) {}
48 LogicalResult visit(
const slang::ast::EmptyMemberSymbol &) {
54 LogicalResult visit(
const slang::ast::TransparentMemberSymbol &) {
59 LogicalResult visit(
const slang::ast::ClassType &classdecl) {
69 LogicalResult visit(
const slang::ast::GenericClassDefSymbol &) {
74 LogicalResult visit(
const slang::ast::TypeAliasType &) {
return success(); }
75 LogicalResult visit(
const slang::ast::ForwardingTypedefSymbol &) {
80 LogicalResult visit(
const slang::ast::ExplicitImportSymbol &) {
83 LogicalResult visit(
const slang::ast::WildcardImportSymbol &) {
88 LogicalResult visit(
const slang::ast::TypeParameterSymbol &) {
93 LogicalResult visit(
const slang::ast::ElabSystemTaskSymbol &) {
98 LogicalResult visit(
const slang::ast::ParameterSymbol ¶m) {
99 visitParameter(param);
103 LogicalResult visit(
const slang::ast::SpecparamSymbol ¶m) {
104 visitParameter(param);
108 template <
class Node>
109 void visitParameter(
const Node ¶m) {
119 if (builder.getInsertionBlock()->getParentOp() == context.
intoModuleOp)
120 context.
orderedRootOps.insert({param.location, value.getDefiningOp()});
124 SmallString<64> paramName;
126 paramName += param.name;
128 debug::VariableOp::create(builder, loc, builder.getStringAttr(paramName),
139struct RootVisitor :
public BaseVisitor {
140 using BaseVisitor::BaseVisitor;
141 using BaseVisitor::visit;
144 LogicalResult visit(
const slang::ast::PackageSymbol &package) {
145 return context.convertPackage(package);
149 LogicalResult visit(
const slang::ast::SubroutineSymbol &subroutine) {
150 return context.convertFunction(subroutine);
154 LogicalResult visit(
const slang::ast::VariableSymbol &var) {
155 return context.convertGlobalVariable(var);
159 template <
typename T>
160 LogicalResult visit(T &&node) {
161 mlir::emitError(loc,
"unsupported construct: ")
162 << slang::ast::toString(node.kind);
173struct PackageVisitor :
public BaseVisitor {
174 using BaseVisitor::BaseVisitor;
175 using BaseVisitor::visit;
178 LogicalResult visit(
const slang::ast::SubroutineSymbol &subroutine) {
179 return context.convertFunction(subroutine);
183 LogicalResult visit(
const slang::ast::VariableSymbol &var) {
184 return context.convertGlobalVariable(var);
188 template <
typename T>
189 LogicalResult visit(T &&node) {
190 mlir::emitError(loc,
"unsupported package member: ")
191 << slang::ast::toString(node.kind);
201static moore::ProcedureKind
204 case slang::ast::ProceduralBlockKind::Always:
205 return moore::ProcedureKind::Always;
206 case slang::ast::ProceduralBlockKind::AlwaysComb:
207 return moore::ProcedureKind::AlwaysComb;
208 case slang::ast::ProceduralBlockKind::AlwaysLatch:
209 return moore::ProcedureKind::AlwaysLatch;
210 case slang::ast::ProceduralBlockKind::AlwaysFF:
211 return moore::ProcedureKind::AlwaysFF;
212 case slang::ast::ProceduralBlockKind::Initial:
213 return moore::ProcedureKind::Initial;
214 case slang::ast::ProceduralBlockKind::Final:
215 return moore::ProcedureKind::Final;
217 llvm_unreachable(
"all procedure kinds handled");
222 case slang::ast::NetType::Supply0:
223 return moore::NetKind::Supply0;
224 case slang::ast::NetType::Supply1:
225 return moore::NetKind::Supply1;
226 case slang::ast::NetType::Tri:
227 return moore::NetKind::Tri;
228 case slang::ast::NetType::TriAnd:
229 return moore::NetKind::TriAnd;
230 case slang::ast::NetType::TriOr:
231 return moore::NetKind::TriOr;
232 case slang::ast::NetType::TriReg:
233 return moore::NetKind::TriReg;
234 case slang::ast::NetType::Tri0:
235 return moore::NetKind::Tri0;
236 case slang::ast::NetType::Tri1:
237 return moore::NetKind::Tri1;
238 case slang::ast::NetType::UWire:
239 return moore::NetKind::UWire;
240 case slang::ast::NetType::Wire:
241 return moore::NetKind::Wire;
242 case slang::ast::NetType::WAnd:
243 return moore::NetKind::WAnd;
244 case slang::ast::NetType::WOr:
245 return moore::NetKind::WOr;
246 case slang::ast::NetType::Interconnect:
247 return moore::NetKind::Interconnect;
248 case slang::ast::NetType::UserDefined:
249 return moore::NetKind::UserDefined;
250 case slang::ast::NetType::Unknown:
251 return moore::NetKind::Unknown;
253 llvm_unreachable(
"all net kinds handled");
257struct ModuleVisitor :
public BaseVisitor {
258 using BaseVisitor::visit;
262 StringRef blockNamePrefix;
264 ModuleVisitor(
Context &
context, Location loc, StringRef blockNamePrefix =
"")
265 : BaseVisitor(
context, loc), blockNamePrefix(blockNamePrefix) {}
268 LogicalResult visit(
const slang::ast::PortSymbol &) {
return success(); }
269 LogicalResult visit(
const slang::ast::MultiPortSymbol &) {
return success(); }
270 LogicalResult visit(
const slang::ast::InterfacePortSymbol &) {
275 LogicalResult visit(
const slang::ast::GenvarSymbol &genvarNode) {
280 LogicalResult visit(
const slang::ast::DefParamSymbol &) {
return success(); }
284 LogicalResult visit(
const slang::ast::TypeParameterSymbol &) {
292 expandInterfaceInstance(
const slang::ast::InstanceSymbol &instNode) {
293 auto prefix = (Twine(blockNamePrefix) + instNode.name +
"_").str();
294 auto lowering = std::make_unique<InterfaceLowering>();
296 for (
const auto &member : instNode.body.members()) {
298 if (
const auto *nestedInst = member.as_if<slang::ast::InstanceSymbol>()) {
299 if (nestedInst->body.getDefinition().definitionKind ==
300 slang::ast::DefinitionKind::Interface)
301 return mlir::emitError(loc)
302 <<
"nested interface instances are not supported: `"
303 << nestedInst->name <<
"` inside `" << instNode.name <<
"`";
306 if (
const auto *var = member.as_if<slang::ast::VariableSymbol>()) {
307 auto loweredType =
context.convertType(*var->getDeclaredType());
310 auto varOp = moore::VariableOp::create(
312 moore::RefType::get(cast<moore::UnpackedType>(loweredType)),
313 builder.getStringAttr(Twine(prefix) + StringRef(var->name)),
315 lowering->expandedMembers[var] = varOp;
319 if (
const auto *net = member.as_if<slang::ast::NetSymbol>()) {
320 auto loweredType =
context.convertType(*net->getDeclaredType());
324 if (netKind == moore::NetKind::Interconnect ||
325 netKind == moore::NetKind::UserDefined ||
326 netKind == moore::NetKind::Unknown)
327 return mlir::emitError(loc,
"unsupported net kind `")
328 << net->netType.name <<
"`";
329 auto netOp = moore::NetOp::create(
331 moore::RefType::get(cast<moore::UnpackedType>(loweredType)),
332 builder.getStringAttr(Twine(prefix) + StringRef(net->name)),
334 lowering->expandedMembers[net] = netOp;
340 context.interfaceInstanceStorage.push_back(std::move(lowering));
341 context.interfaceInstances.insert(
342 &instNode,
context.interfaceInstanceStorage.back().get());
347 LogicalResult visit(
const slang::ast::InstanceSymbol &instNode) {
348 using slang::ast::ArgumentDirection;
349 using slang::ast::AssignmentExpression;
350 using slang::ast::MultiPortSymbol;
351 using slang::ast::PortSymbol;
355 auto defKind = instNode.body.getDefinition().definitionKind;
356 if (defKind == slang::ast::DefinitionKind::Interface)
357 return expandInterfaceInstance(instNode);
359 auto *moduleLowering =
context.convertModuleHeader(&instNode.body);
362 auto module = moduleLowering->op;
363 auto moduleType =
module.getModuleType();
366 SymbolTable::setSymbolVisibility(module, SymbolTable::Visibility::Private);
373 portValues.reserve(moduleType.getNumPorts());
377 const slang::ast::InstanceSymbol *>
380 for (
const auto *con : instNode.getPortConnections()) {
381 const auto *expr = con->getExpression();
386 auto *port = con->port.as_if<PortSymbol>();
387 if (
auto *existingPort =
388 moduleLowering->portsBySyntaxNode.lookup(port->getSyntax()))
391 switch (port->direction) {
392 case ArgumentDirection::In: {
393 auto refType = moore::RefType::get(
394 cast<moore::UnpackedType>(
context.convertType(port->getType())));
396 if (
const auto *net =
397 port->internalSymbol->as_if<slang::ast::NetSymbol>()) {
398 auto netOp = moore::NetOp::create(
399 builder, loc, refType,
400 StringAttr::get(builder.getContext(), net->name),
402 auto readOp = moore::ReadOp::create(builder, loc, netOp);
403 portValues.insert({port, readOp});
404 }
else if (
const auto *var =
406 ->as_if<slang::ast::VariableSymbol>()) {
407 auto varOp = moore::VariableOp::create(
408 builder, loc, refType,
409 StringAttr::get(builder.getContext(), var->name),
nullptr);
410 auto readOp = moore::ReadOp::create(builder, loc, varOp);
411 portValues.insert({port, readOp});
413 return mlir::emitError(loc)
414 <<
"unsupported internal symbol for unconnected port `"
415 << port->name <<
"`";
422 case ArgumentDirection::Out:
425 case ArgumentDirection::InOut:
426 case ArgumentDirection::Ref: {
427 auto refType = moore::RefType::get(
428 cast<moore::UnpackedType>(
context.convertType(port->getType())));
430 if (
const auto *net =
431 port->internalSymbol->as_if<slang::ast::NetSymbol>()) {
432 auto netOp = moore::NetOp::create(
433 builder, loc, refType,
434 StringAttr::get(builder.getContext(), net->name),
436 portValues.insert({port, netOp});
437 }
else if (
const auto *var =
439 ->as_if<slang::ast::VariableSymbol>()) {
440 auto varOp = moore::VariableOp::create(
441 builder, loc, refType,
442 StringAttr::get(builder.getContext(), var->name),
nullptr);
443 portValues.insert({port, varOp});
445 return mlir::emitError(loc)
446 <<
"unsupported internal symbol for unconnected port `"
447 << port->name <<
"`";
456 if (
const auto *assign = expr->as_if<AssignmentExpression>())
457 expr = &assign->left();
462 if (
auto *port = con->port.as_if<PortSymbol>()) {
464 auto value = (port->direction == ArgumentDirection::In)
465 ?
context.convertRvalueExpression(*expr)
466 :
context.convertLvalueExpression(*expr);
469 if (
auto *existingPort =
470 moduleLowering->portsBySyntaxNode.lookup(con->port.getSyntax()))
472 portValues.insert({port, value});
479 if (
const auto *multiPort = con->port.as_if<MultiPortSymbol>()) {
481 auto value =
context.convertLvalueExpression(*expr);
485 for (
const auto *port :
llvm::reverse(multiPort->ports)) {
486 if (
auto *existingPort = moduleLowering->portsBySyntaxNode.lookup(
487 con->port.getSyntax()))
489 unsigned width = port->getType().getBitWidth();
490 auto sliceType =
context.convertType(port->getType());
493 Value slice = moore::ExtractRefOp::create(
495 moore::RefType::get(cast<moore::UnpackedType>(sliceType)), value,
498 if (port->direction == ArgumentDirection::In)
499 slice = moore::ReadOp::create(builder, loc, slice);
500 portValues.insert({port, slice});
508 if (
const auto *ifacePort =
509 con->port.as_if<slang::ast::InterfacePortSymbol>()) {
510 auto ifaceConn = con->getIfaceConn();
511 const auto *connInst =
512 ifaceConn.first->as_if<slang::ast::InstanceSymbol>();
514 ifaceConnMap[ifacePort] = connInst;
518 mlir::emitError(loc) <<
"unsupported instance port `" << con->port.name
519 <<
"` (" << slang::ast::toString(con->port.kind)
525 SmallVector<Value> inputValues;
526 SmallVector<Value> outputValues;
527 inputValues.reserve(moduleType.getNumInputs());
528 outputValues.reserve(moduleType.getNumOutputs());
530 for (
auto &port : moduleLowering->ports) {
531 auto value = portValues.lookup(&port.ast);
532 if (port.ast.direction == ArgumentDirection::Out)
533 outputValues.push_back(value);
535 inputValues.push_back(value);
541 for (
auto &fp : moduleLowering->ifacePorts) {
542 if (!fp.bodySym || !fp.origin)
545 auto it = ifaceConnMap.find(fp.origin);
546 if (it == ifaceConnMap.end()) {
548 <<
"no interface connection for port `" << fp.name <<
"`";
551 const auto *connInst = it->second;
553 auto *ifaceLowering =
context.interfaceInstances.lookup(connInst);
554 if (!ifaceLowering) {
556 <<
"interface instance `" << connInst->name <<
"` was not expanded";
560 auto valIt = ifaceLowering->expandedMembers.find(fp.bodySym);
561 if (valIt == ifaceLowering->expandedMembers.end()) {
563 <<
"unresolved interface port signal `" << fp.name <<
"`";
566 Value val = valIt->second;
568 outputValues.push_back(val);
572 if (isa<moore::RefType>(val.getType()))
573 val = moore::ReadOp::create(builder, loc, val);
574 inputValues.push_back(val);
579 for (
auto [value, type] :
580 llvm::zip(inputValues, moduleType.getInputTypes()))
582 value =
context.materializeConversion(type, value, false, value.
getLoc());
586 for (
const auto &hierPath :
context.hierPaths[&instNode.body])
587 if (auto hierValue =
context.valueSymbols.lookup(hierPath.valueSym);
588 hierPath.hierName && hierPath.direction == ArgumentDirection::In)
589 inputValues.push_back(hierValue);
592 auto inputNames = builder.getArrayAttr(moduleType.getInputNames());
593 auto outputNames = builder.getArrayAttr(moduleType.getOutputNames());
594 auto inst = moore::InstanceOp::create(
595 builder, loc, moduleType.getOutputTypes(),
596 builder.getStringAttr(Twine(blockNamePrefix) + instNode.name),
597 FlatSymbolRefAttr::get(module.getSymNameAttr()), inputValues,
598 inputNames, outputNames);
601 for (
const auto &hierPath :
context.hierPaths[&instNode.body])
602 if (hierPath.idx && hierPath.direction == ArgumentDirection::
Out)
603 context.valueSymbols.insert(hierPath.valueSym,
604 inst->getResult(*hierPath.idx));
607 for (
auto [lvalue, output] :
llvm::zip(outputValues, inst.getOutputs())) {
610 Value rvalue = output;
611 auto dstType = cast<moore::RefType>(lvalue.getType()).getNestedType();
613 rvalue =
context.materializeConversion(dstType, rvalue,
false, loc);
614 moore::ContinuousAssignOp::create(builder, loc, lvalue, rvalue);
621 LogicalResult visit(
const slang::ast::VariableSymbol &varNode) {
622 auto loweredType =
context.convertType(*varNode.getDeclaredType());
627 if (
const auto *init = varNode.getInitializer()) {
628 initial =
context.convertRvalueExpression(*init, loweredType);
633 auto varOp = moore::VariableOp::create(
635 moore::RefType::get(cast<moore::UnpackedType>(loweredType)),
636 builder.getStringAttr(Twine(blockNamePrefix) + varNode.name), initial);
637 context.valueSymbols.insert(&varNode, varOp);
642 LogicalResult visit(
const slang::ast::NetSymbol &netNode) {
643 auto loweredType =
context.convertType(*netNode.getDeclaredType());
648 if (
const auto *init = netNode.getInitializer()) {
649 assignment =
context.convertRvalueExpression(*init, loweredType);
655 if (netkind == moore::NetKind::Interconnect ||
656 netkind == moore::NetKind::UserDefined ||
657 netkind == moore::NetKind::Unknown)
658 return mlir::emitError(loc,
"unsupported net kind `")
659 << netNode.netType.name <<
"`";
661 auto netOp = moore::NetOp::create(
663 moore::RefType::get(cast<moore::UnpackedType>(loweredType)),
664 builder.getStringAttr(Twine(blockNamePrefix) + netNode.name), netkind,
666 context.valueSymbols.insert(&netNode, netOp);
671 LogicalResult visit(
const slang::ast::ContinuousAssignSymbol &assignNode) {
673 assignNode.getAssignment().as<slang::ast::AssignmentExpression>();
674 auto lhs =
context.convertLvalueExpression(expr.left());
678 auto rhs =
context.convertRvalueExpression(
679 expr.right(), cast<moore::RefType>(lhs.getType()).getNestedType());
684 if (
auto *timingCtrl = assignNode.getDelay()) {
685 auto *ctrl = timingCtrl->as_if<slang::ast::DelayControl>();
686 assert(ctrl &&
"slang guarantees this to be a simple delay");
687 auto delay =
context.convertRvalueExpression(
688 ctrl->expr, moore::TimeType::get(builder.getContext()));
691 moore::DelayedContinuousAssignOp::create(builder, loc, lhs, rhs, delay);
696 moore::ContinuousAssignOp::create(builder, loc, lhs, rhs);
701 LogicalResult convertProcedure(moore::ProcedureKind kind,
702 const slang::ast::Statement &body) {
703 if (body.as_if<slang::ast::ConcurrentAssertionStatement>())
704 return context.convertStatement(body);
705 auto procOp = moore::ProcedureOp::create(builder, loc, kind);
706 OpBuilder::InsertionGuard guard(builder);
707 builder.setInsertionPointToEnd(&procOp.getBody().emplaceBlock());
708 Context::ValueSymbolScope scope(
context.valueSymbols);
709 if (failed(
context.convertStatement(body)))
711 if (builder.getBlock())
712 moore::ReturnOp::create(builder, loc);
716 LogicalResult visit(
const slang::ast::ProceduralBlockSymbol &procNode) {
719 if (
context.options.lowerAlwaysAtStarAsComb) {
720 auto *stmt = procNode.getBody().as_if<slang::ast::TimedStatement>();
721 if (procNode.procedureKind == slang::ast::ProceduralBlockKind::Always &&
723 stmt->timing.kind == slang::ast::TimingControlKind::ImplicitEvent)
724 return convertProcedure(moore::ProcedureKind::AlwaysComb, stmt->stmt);
732 LogicalResult visit(
const slang::ast::GenerateBlockSymbol &genNode) {
734 if (genNode.isUninstantiated)
738 SmallString<64> prefix = blockNamePrefix;
739 if (!genNode.name.empty() ||
740 genNode.getParentScope()->asSymbol().kind !=
741 slang::ast::SymbolKind::GenerateBlockArray) {
742 prefix += genNode.getExternalName();
747 for (
auto &member : genNode.members())
748 if (failed(member.visit(ModuleVisitor(
context, loc, prefix))))
754 LogicalResult visit(
const slang::ast::GenerateBlockArraySymbol &genArrNode) {
757 SmallString<64> prefix = blockNamePrefix;
758 prefix += genArrNode.getExternalName();
760 auto prefixBaseLen = prefix.size();
763 for (
const auto *entry : genArrNode.entries) {
765 prefix.resize(prefixBaseLen);
766 if (entry->arrayIndex)
767 prefix += entry->arrayIndex->toString();
769 Twine(entry->constructIndex).toVector(prefix);
773 if (failed(entry->asSymbol().visit(ModuleVisitor(
context, loc, prefix))))
785 LogicalResult visit(
const slang::ast::StatementBlockSymbol &) {
791 LogicalResult visit(
const slang::ast::SequenceSymbol &seqNode) {
797 LogicalResult visit(
const slang::ast::PropertySymbol &propNode) {
802 LogicalResult visit(
const slang::ast::SubroutineSymbol &subroutine) {
803 return context.convertFunction(subroutine);
807 template <
typename T>
808 LogicalResult visit(T &&node) {
809 mlir::emitError(loc,
"unsupported module member: ")
810 << slang::ast::toString(node.kind);
822LogicalResult Context::convertCompilation() {
828 timeScale = root.getTimeScale().value_or(slang::TimeScale());
829 llvm::scope_exit timeScaleGuard([&] {
timeScale = prevTimeScale; });
833 for (
auto *inst : root.topInstances)
840 for (
auto *unit : root.compilationUnits) {
841 for (
const auto &member : unit->members()) {
843 if (failed(member.visit(RootVisitor(*
this, loc))))
851 SmallVector<const slang::ast::InstanceSymbol *> topInstances;
852 for (
auto *inst : root.topInstances)
853 if (inst->body.getDefinition().definitionKind !=
854 slang::ast::DefinitionKind::Interface)
860 auto *
module = moduleWorklist.front();
868 SmallVector<const slang::ast::ClassType *, 16> classMethodWorklist;
869 classMethodWorklist.reserve(
classes.size());
871 classMethodWorklist.push_back(kv.first);
873 for (
auto *inst : classMethodWorklist) {
881 auto &block = varOp.getInitRegion().emplaceBlock();
882 OpBuilder::InsertionGuard guard(
builder);
883 builder.setInsertionPointToEnd(&block);
888 moore::YieldOp::create(
builder, varOp.getLoc(), value);
901 using slang::ast::ArgumentDirection;
902 using slang::ast::MultiPortSymbol;
903 using slang::ast::ParameterSymbol;
904 using slang::ast::PortSymbol;
905 using slang::ast::TypeParameterSymbol;
910 timeScale =
module->getTimeScale().value_or(slang::TimeScale());
911 llvm::scope_exit timeScaleGuard([&] {
timeScale = prevTimeScale; });
913 auto parameters =
module->getParameters();
914 bool hasModuleSame =
false;
918 for (
auto const &existingModule :
modules) {
919 if (module->getDeclaringDefinition() ==
920 existingModule.getFirst()->getDeclaringDefinition()) {
921 auto moduleParameters = existingModule.getFirst()->getParameters();
922 hasModuleSame =
true;
923 for (
auto it1 = parameters.begin(), it2 = moduleParameters.begin();
924 it1 != parameters.end() && it2 != moduleParameters.end();
927 if (it1 == parameters.end() || it2 == moduleParameters.end()) {
928 hasModuleSame =
false;
931 const auto *para1 = (*it1)->symbol.as_if<ParameterSymbol>();
932 const auto *para2 = (*it2)->symbol.as_if<ParameterSymbol>();
934 if ((para1 ==
nullptr) ^ (para2 ==
nullptr)) {
935 hasModuleSame =
false;
939 if (para1 !=
nullptr) {
940 hasModuleSame = para1->getValue() == para2->getValue();
943 if (para1 ==
nullptr) {
945 (*it1)->symbol.as<TypeParameterSymbol>().getTypeAlias());
947 (*it2)->symbol.as<TypeParameterSymbol>().getTypeAlias());
948 hasModuleSame = para1Type == para2Type;
954 module = existingModule.first;
963 slot = std::make_unique<ModuleLowering>();
964 auto &lowering = *slot;
967 OpBuilder::InsertionGuard g(
builder);
972 auto kind =
module->getDefinition().definitionKind;
973 if (kind != slang::ast::DefinitionKind::Module &&
974 kind != slang::ast::DefinitionKind::Program) {
975 mlir::emitError(loc) <<
"unsupported definition: "
976 <<
module->getDefinition().getKindString();
981 auto block = std::make_unique<Block>();
982 SmallVector<hw::ModulePort> modulePorts;
985 unsigned int outputIdx = 0, inputIdx = 0;
986 for (
auto *symbol :
module->getPortList()) {
987 auto handlePort = [&](const PortSymbol &port) {
988 auto portLoc = convertLocation(port.location);
992 auto portName =
builder.getStringAttr(port.name);
994 if (port.direction == ArgumentDirection::Out) {
1000 if (port.direction != ArgumentDirection::In)
1001 type = moore::RefType::get(cast<moore::UnpackedType>(type));
1003 arg = block->addArgument(type, portLoc);
1006 lowering.ports.push_back({port, portLoc, arg});
1013 auto handleIfacePort = [&](
const slang::ast::InterfacePortSymbol
1016 auto [connSym, modportSym] = ifacePort.getConnection();
1017 auto portPrefix = (Twine(ifacePort.name) +
"_").str();
1021 for (
const auto &member : modportSym->members()) {
1022 const auto *mpp = member.as_if<slang::ast::ModportPortSymbol>();
1029 builder.getStringAttr(Twine(portPrefix) + StringRef(mpp->name));
1032 if (mpp->direction == ArgumentDirection::Out) {
1034 modulePorts.push_back({name, type, dir});
1038 if (mpp->direction != ArgumentDirection::In)
1039 type = moore::RefType::get(cast<moore::UnpackedType>(type));
1040 modulePorts.push_back({name, type, dir});
1041 arg = block->addArgument(type, portLoc);
1044 lowering.ifacePorts.push_back(
1045 {name, dir, type, portLoc, arg, &ifacePort, mpp->internalSymbol});
1050 const auto *instSym = connSym->as_if<slang::ast::InstanceSymbol>();
1052 mlir::emitError(portLoc)
1053 <<
"unsupported interface port connection for `" << ifacePort.name
1057 for (
const auto &member : instSym->body.members()) {
1058 const slang::ast::Type *slangType =
nullptr;
1059 const slang::ast::Symbol *bodySym =
nullptr;
1060 if (
const auto *var = member.as_if<slang::ast::VariableSymbol>()) {
1061 slangType = &var->getType();
1063 }
else if (
const auto *net = member.as_if<slang::ast::NetSymbol>()) {
1064 slangType = &net->getType();
1072 auto name = builder.getStringAttr(Twine(portPrefix) +
1073 StringRef(bodySym->name));
1074 auto refType = moore::RefType::get(cast<moore::UnpackedType>(type));
1076 auto arg = block->addArgument(refType, portLoc);
1079 portLoc, arg, &ifacePort, bodySym});
1085 if (
const auto *port = symbol->as_if<PortSymbol>()) {
1086 if (failed(handlePort(*port)))
1088 }
else if (
const auto *multiPort = symbol->as_if<MultiPortSymbol>()) {
1089 for (
auto *port : multiPort->ports)
1090 if (failed(handlePort(*port)))
1092 }
else if (
const auto *ifacePort =
1093 symbol->as_if<slang::ast::InterfacePortSymbol>()) {
1094 if (failed(handleIfacePort(*ifacePort)))
1098 <<
"unsupported module port `" << symbol->name <<
"` ("
1099 << slang::ast::toString(symbol->kind) <<
")";
1105 for (
auto &hierPath : hierPaths[module]) {
1106 auto hierType =
convertType(hierPath.valueSym->getType());
1110 if (
auto hierName = hierPath.hierName) {
1112 hierType = moore::RefType::get(cast<moore::UnpackedType>(hierType));
1113 if (hierPath.direction == ArgumentDirection::Out) {
1114 hierPath.idx = outputIdx++;
1117 hierPath.idx = inputIdx++;
1120 block->addArgument(hierType, hierLoc);
1124 auto moduleType = hw::ModuleType::get(getContext(), modulePorts);
1128 auto it = orderedRootOps.upper_bound(module->location);
1129 if (it == orderedRootOps.end())
1130 builder.setInsertionPointToEnd(intoModuleOp.getBody());
1132 builder.setInsertionPoint(it->second);
1136 moore::SVModuleOp::create(builder, loc, module->name, moduleType);
1137 orderedRootOps.insert(it, {
module->location, moduleOp});
1138 moduleOp.getBodyRegion().push_back(block.release());
1139 lowering.op = moduleOp;
1143 symbolTable.insert(moduleOp);
1146 moduleWorklist.push(module);
1149 for (
const auto &port : lowering.ports)
1150 lowering.portsBySyntaxNode.insert({port.ast.getSyntax(), &port.ast});
1159 auto &lowering = *
modules[module];
1160 OpBuilder::InsertionGuard g(
builder);
1161 builder.setInsertionPointToEnd(lowering.op.getBody());
1169 timeScale =
module->getTimeScale().value_or(slang::TimeScale());
1170 llvm::scope_exit timeScaleGuard([&] {
timeScale = prevTimeScale; });
1175 for (
auto &hierPath :
hierPaths[module])
1176 if (hierPath.direction == slang::ast::ArgumentDirection::In && hierPath.idx)
1178 lowering.op.getBody()->getArgument(*hierPath.idx));
1181 for (
auto &member :
module->members()) {
1182 auto loc = convertLocation(member.location);
1183 if (failed(member.visit(ModuleVisitor(*
this, loc))))
1190 SmallVector<Value> outputs;
1191 for (
auto &port : lowering.ports) {
1193 if (
auto *expr = port.ast.getInternalExpr()) {
1194 value = convertLvalueExpression(*expr);
1195 }
else if (port.ast.internalSymbol) {
1196 if (
const auto *sym =
1197 port.ast.internalSymbol->as_if<slang::ast::ValueSymbol>())
1198 value = valueSymbols.lookup(sym);
1201 return mlir::emitError(port.loc,
"unsupported port: `")
1203 <<
"` does not map to an internal symbol or expression";
1206 if (port.ast.direction == slang::ast::ArgumentDirection::Out) {
1207 if (isa<moore::RefType>(value.getType()))
1208 value = moore::ReadOp::create(builder, value.getLoc(), value);
1209 outputs.push_back(value);
1215 Value portArg = port.arg;
1216 if (port.ast.direction != slang::ast::ArgumentDirection::In)
1217 portArg = moore::ReadOp::create(builder, port.loc, port.arg);
1218 moore::ContinuousAssignOp::create(builder, port.loc, value, portArg);
1224 for (
auto &fp : lowering.ifacePorts) {
1231 auto *valueSym = fp.bodySym->as_if<slang::ast::ValueSymbol>();
1238 auto varOp = moore::VariableOp::create(
1240 moore::RefType::get(cast<moore::UnpackedType>(fp.type)), fp.name,
1242 valueSymbols.insert(valueSym, varOp);
1243 auto readVal = moore::ReadOp::create(builder, fp.loc, varOp);
1244 outputs.push_back(readVal);
1248 valueSymbols.insert(valueSym, fp.arg);
1254 for (
auto &hierPath : hierPaths[module])
1255 if (auto hierValue = valueSymbols.lookup(hierPath.valueSym))
1256 if (hierPath.direction == slang::ast::ArgumentDirection::
Out)
1257 outputs.push_back(hierValue);
1259 moore::OutputOp::create(builder, lowering.op.getLoc(), outputs);
1269 timeScale = package.getTimeScale().value_or(slang::TimeScale());
1270 llvm::scope_exit timeScaleGuard([&] {
timeScale = prevTimeScale; });
1272 OpBuilder::InsertionGuard g(
builder);
1275 for (
auto &member : package.members()) {
1277 if (failed(member.visit(PackageVisitor(*
this, loc))))
1288 auto &lowering =
functions[&subroutine];
1292 return lowering.get();
1295 if (!subroutine.thisVar) {
1297 SmallString<64> name;
1299 name += subroutine.name;
1301 SmallVector<Type, 1> noThis = {};
1308 const slang::ast::Type &thisTy = subroutine.thisVar->getType();
1309 moore::ClassDeclOp ownerDecl;
1311 if (
auto *classTy = thisTy.as_if<slang::ast::ClassType>()) {
1312 auto &ownerLowering =
classes[classTy];
1313 ownerDecl = ownerLowering->op;
1315 mlir::emitError(loc) <<
"expected 'this' to be a class type, got "
1316 << thisTy.toString();
1321 SmallString<64> qualName;
1322 qualName += ownerDecl.getSymName();
1324 qualName += subroutine.name;
1327 SmallVector<Type, 1> extraParams;
1329 auto classSym = mlir::FlatSymbolRefAttr::get(ownerDecl.getSymNameAttr());
1330 auto handleTy = moore::ClassHandleType::get(
getContext(), classSym);
1331 extraParams.push_back(handleTy);
1342 const slang::ast::SubroutineSymbol &subroutine,
1343 llvm::SmallVectorImpl<Type> &extraParams) {
1344 using slang::ast::ArgumentDirection;
1346 SmallVector<Type> inputTypes;
1347 inputTypes.append(extraParams.begin(), extraParams.end());
1348 SmallVector<Type, 1> outputTypes;
1350 for (
const auto *arg : subroutine.getArguments()) {
1351 auto type =
context.convertType(arg->getType());
1354 if (arg->direction == ArgumentDirection::In) {
1355 inputTypes.push_back(type);
1357 inputTypes.push_back(
1358 moore::RefType::get(cast<moore::UnpackedType>(type)));
1362 const auto &returnType = subroutine.getReturnType();
1363 if (!returnType.isVoid()) {
1364 auto type =
context.convertType(returnType);
1367 outputTypes.push_back(type);
1371 FunctionType::get(
context.getContext(), inputTypes, outputTypes);
1381 mlir::StringRef qualifiedName,
1382 llvm::SmallVectorImpl<Type> &extraParams) {
1384 std::unique_ptr<FunctionLowering> lowering =
1385 std::make_unique<FunctionLowering>();
1389 OpBuilder::InsertionGuard g(
builder);
1394 builder.setInsertionPoint(it->second);
1399 auto funcOp = mlir::func::FuncOp::create(
builder, loc, qualifiedName, funcTy);
1401 SymbolTable::setSymbolVisibility(funcOp, SymbolTable::Visibility::Private);
1403 lowering->op = funcOp;
1408 functions[&subroutine] = std::move(lowering);
1417 ArrayRef<Value> captures) {
1418 if (captures.empty())
1421 mlir::ModuleOp
module = callee->getParentOfType<mlir::ModuleOp>();
1423 return callee.emitError(
"expected callee to be nested under ModuleOp");
1425 auto usesOpt = mlir::SymbolTable::getSymbolUses(callee, module);
1427 return callee.emitError(
"failed to compute symbol uses");
1430 SmallVector<mlir::func::CallOp, 8> callSites;
1431 callSites.reserve(std::distance(usesOpt->begin(), usesOpt->end()));
1432 for (
const mlir::SymbolTable::SymbolUse &use : *usesOpt) {
1433 if (
auto call = llvm::dyn_cast<mlir::func::CallOp>(use.getUser()))
1434 callSites.push_back(call);
1436 if (callSites.empty())
1439 Block &entry = callee.getBody().front();
1440 const unsigned numCaps = captures.size();
1441 const unsigned numEntryArgs = entry.getNumArguments();
1442 if (numEntryArgs < numCaps)
1443 return callee.emitError(
"entry block has fewer args than captures");
1444 const unsigned capArgStart = numEntryArgs - numCaps;
1447 auto fTy = callee.getFunctionType();
1449 for (
auto call : callSites) {
1450 SmallVector<Value> newOperands(call.getArgOperands().begin(),
1451 call.getArgOperands().end());
1453 const bool inSameFunc = callee->isProperAncestor(call);
1456 for (
unsigned i = 0; i < numCaps; ++i)
1457 newOperands.push_back(entry.getArgument(capArgStart + i));
1460 newOperands.append(captures.begin(), captures.end());
1464 auto flatRef = mlir::FlatSymbolRefAttr::get(callee);
1465 auto newCall = mlir::func::CallOp::create(
1466 b, call.getLoc(), fTy.getResults(), flatRef, newOperands);
1467 call->replaceAllUsesWith(newCall.getOperation());
1480 timeScale = subroutine.getTimeScale().value_or(slang::TimeScale());
1481 llvm::scope_exit timeScaleGuard([&] {
timeScale = prevTimeScale; });
1490 if (lowering->capturesFinalized || lowering->isConverting)
1496 if (subroutine.flags.has(slang::ast::MethodFlags::DPIImport)) {
1497 lowering->capturesFinalized =
true;
1501 const bool isMethod = (subroutine.thisVar !=
nullptr);
1506 SmallVector<moore::VariableOp> argVariables;
1507 auto &block = lowering->op.getBody().emplaceBlock();
1513 auto thisType = lowering->op.getFunctionType().getInput(0);
1514 auto thisArg = block.addArgument(thisType, thisLoc);
1521 auto inputs = lowering->op.getFunctionType().getInputs();
1522 auto astArgs = subroutine.getArguments();
1523 auto valInputs = llvm::ArrayRef<Type>(inputs).drop_front(isMethod ? 1 : 0);
1525 for (
auto [astArg, type] : llvm::zip(astArgs, valInputs)) {
1527 auto blockArg = block.addArgument(type, loc);
1529 if (isa<moore::RefType>(type)) {
1532 OpBuilder::InsertionGuard g(
builder);
1533 builder.setInsertionPointToEnd(&block);
1535 auto shadowArg = moore::VariableOp::create(
1536 builder, loc, moore::RefType::get(cast<moore::UnpackedType>(type)),
1537 StringAttr{}, blockArg);
1539 argVariables.push_back(shadowArg);
1544 OpBuilder::InsertionGuard g(
builder);
1545 builder.setInsertionPointToEnd(&block);
1548 if (subroutine.returnValVar) {
1549 auto type =
convertType(*subroutine.returnValVar->getDeclaredType());
1552 returnVar = moore::VariableOp::create(
1553 builder, lowering->op.getLoc(),
1554 moore::RefType::get(cast<moore::UnpackedType>(type)), StringAttr{},
1556 valueSymbols.insert(subroutine.returnValVar, returnVar);
1562 llvm::scope_exit prevRCbGuard([&] {
1569 mlir::Value ref = rop.getInput();
1572 mlir::Type ty = ref.getType();
1573 if (!ty || !(isa<moore::RefType>(ty)))
1577 mlir::Region *defReg = ref.getParentRegion();
1578 if (defReg && lowering->op.getBody().isAncestor(defReg))
1582 if (lowering->captureIndex.count(ref))
1586 auto [it, inserted] =
1587 lowering->captureIndex.try_emplace(ref, lowering->captures.size());
1589 lowering->captures.push_back(ref);
1597 mlir::Value dstRef =
1598 llvm::TypeSwitch<mlir::Operation *, mlir::Value>(op)
1599 .Case<moore::BlockingAssignOp, moore::NonBlockingAssignOp,
1600 moore::DelayedNonBlockingAssignOp>(
1601 [](
auto op) {
return op.getDst(); })
1602 .Default([](
auto) -> mlir::Value {
return {}; });
1605 mlir::Type ty = dstRef.getType();
1606 if (!ty || !(isa<moore::RefType>(ty)))
1610 mlir::Region *defReg = dstRef.getParentRegion();
1611 if (defReg && lowering->op.getBody().isAncestor(defReg))
1615 if (lowering->captureIndex.count(dstRef))
1619 auto [it, inserted] =
1620 lowering->captureIndex.try_emplace(dstRef, lowering->captures.size());
1622 lowering->captures.push_back(dstRef);
1631 llvm::scope_exit restoreThis([&] {
currentThisRef = savedThis; });
1633 lowering->isConverting =
true;
1634 llvm::scope_exit convertingGuard([&] { lowering->isConverting =
false; });
1651 if (returnVar && !subroutine.getReturnType().isVoid()) {
1653 moore::ReadOp::create(
builder, returnVar.getLoc(), returnVar);
1654 mlir::func::ReturnOp::create(
builder, lowering->op.getLoc(), read);
1656 mlir::func::ReturnOp::create(
builder, lowering->op.getLoc(),
1660 if (returnVar && returnVar.use_empty())
1661 returnVar.getDefiningOp()->erase();
1663 for (
auto var : argVariables) {
1664 if (llvm::all_of(var->getUsers(),
1665 [](
auto *user) { return isa<moore::ReadOp>(user); })) {
1666 for (
auto *user : llvm::make_early_inc_range(var->getUsers())) {
1667 user->getResult(0).replaceAllUsesWith(var.getInitial());
1674 lowering->capturesFinalized =
true;
1686 SmallVector<Type> newInputs(lowering.
op.getFunctionType().getInputs().begin(),
1687 lowering.
op.getFunctionType().getInputs().end());
1689 for (Value cap : lowering.
captures) {
1691 Type capTy = cap.getType();
1692 if (!isa<moore::RefType>(capTy)) {
1693 return lowering.
op.emitError(
1694 "expected captured value to be a ref-like type");
1696 newInputs.push_back(capTy);
1700 auto newFuncTy = FunctionType::get(
1701 ctx, newInputs, lowering.
op.getFunctionType().getResults());
1702 lowering.
op.setFunctionType(newFuncTy);
1705 Block &entry = lowering.
op.getBody().front();
1706 SmallVector<Value> capArgs;
1707 capArgs.reserve(lowering.
captures.size());
1709 llvm::ArrayRef<Type>(newInputs).take_back(lowering.
captures.size())) {
1710 capArgs.push_back(entry.addArgument(t, lowering.
op.getLoc()));
1716 Value arg = capArgs[idx];
1717 cap.replaceUsesWithIf(arg, [&](OpOperand &use) {
1718 return lowering.
op->isProperAncestor(use.getOwner());
1729mlir::StringAttr fullyQualifiedClassName(
Context &ctx,
1730 const slang::ast::Type &ty) {
1731 SmallString<64> name;
1732 SmallVector<llvm::StringRef, 8> parts;
1734 const slang::ast::Scope *scope = ty.getParentScope();
1736 const auto &sym = scope->asSymbol();
1738 case slang::ast::SymbolKind::Root:
1741 case slang::ast::SymbolKind::InstanceBody:
1742 case slang::ast::SymbolKind::Instance:
1743 case slang::ast::SymbolKind::Package:
1744 case slang::ast::SymbolKind::ClassType:
1745 if (!sym.name.empty())
1746 parts.push_back(sym.name);
1751 scope = sym.getParentScope();
1754 for (
auto p :
llvm::reverse(parts)) {
1759 return mlir::StringAttr::get(ctx.
getContext(), name);
1764std::pair<mlir::SymbolRefAttr, mlir::ArrayAttr>
1766 const slang::ast::ClassType &cls) {
1770 mlir::SymbolRefAttr base;
1771 if (
const auto *b = cls.getBaseClass())
1772 base = mlir::SymbolRefAttr::get(fullyQualifiedClassName(
context, *b));
1775 SmallVector<mlir::Attribute> impls;
1776 if (
auto ifaces = cls.getDeclaredInterfaces(); !ifaces.empty()) {
1777 impls.reserve(ifaces.size());
1778 for (
const auto *iface : ifaces)
1779 impls.push_back(
mlir::FlatSymbolRefAttr::
get(
1780 fullyQualifiedClassName(
context, *iface)));
1783 mlir::ArrayAttr implArr =
1784 impls.empty() ? mlir::ArrayAttr() :
mlir::ArrayAttr::
get(ctx, impls);
1786 return {base, implArr};
1791struct ClassDeclVisitorBase {
1797 :
context(ctx), builder(ctx.builder), classLowering(lowering) {}
1801 return context.convertLocation(sloc);
1807struct ClassPropertyVisitor : ClassDeclVisitorBase {
1808 using ClassDeclVisitorBase::ClassDeclVisitorBase;
1811 LogicalResult
run(
const slang::ast::ClassType &classAST) {
1812 if (!classLowering.
op.getBody().empty())
1815 OpBuilder::InsertionGuard ig(builder);
1817 Block *body = &classLowering.
op.getBody().emplaceBlock();
1818 builder.setInsertionPointToEnd(body);
1821 for (
const auto &mem : classAST.members()) {
1822 if (
const auto *prop = mem.as_if<slang::ast::ClassPropertySymbol>()) {
1823 if (failed(prop->visit(*
this)))
1832 LogicalResult visit(
const slang::ast::ClassPropertySymbol &prop) {
1834 auto ty =
context.convertType(prop.getType());
1838 if (prop.lifetime == slang::ast::VariableLifetime::Automatic) {
1839 moore::ClassPropertyDeclOp::create(builder, loc, prop.name, ty);
1847 if (!
context.globalVariables.lookup(&prop))
1848 return context.convertGlobalVariable(prop);
1853 LogicalResult visit(
const slang::ast::ClassType &cls) {
1854 return context.buildClassProperties(cls);
1858 template <
typename T>
1859 LogicalResult visit(T &&) {
1866struct ClassMethodVisitor : ClassDeclVisitorBase {
1867 using ClassDeclVisitorBase::ClassDeclVisitorBase;
1870 LogicalResult
run(
const slang::ast::ClassType &classAST) {
1874 if (classLowering.
op.getBody().empty())
1877 OpBuilder::InsertionGuard ig(builder);
1878 builder.setInsertionPointToEnd(&classLowering.
op.getBody().front());
1881 for (
const auto &mem : classAST.members()) {
1882 if (failed(mem.visit(*
this)))
1891 LogicalResult visit(
const slang::ast::ClassPropertySymbol &) {
1897 LogicalResult visit(
const slang::ast::ParameterSymbol &) {
return success(); }
1901 LogicalResult visit(
const slang::ast::TypeParameterSymbol &) {
1907 LogicalResult visit(
const slang::ast::TypeAliasType &) {
return success(); }
1910 LogicalResult visit(
const slang::ast::GenericClassDefSymbol &) {
1915 LogicalResult visit(
const slang::ast::TransparentMemberSymbol &) {
1920 LogicalResult visit(
const slang::ast::EmptyMemberSymbol &) {
1925 LogicalResult visit(
const slang::ast::SubroutineSymbol &fn) {
1926 if (fn.flags & slang::ast::MethodFlags::BuiltIn) {
1927 static bool remarkEmitted =
false;
1931 mlir::emitRemark(classLowering.
op.getLoc())
1932 <<
"Class builtin functions (needed for randomization, constraints, "
1933 "and covergroups) are not yet supported and will be dropped "
1935 remarkEmitted =
true;
1939 const mlir::UnitAttr isVirtual =
1940 (fn.flags & slang::ast::MethodFlags::Virtual)
1941 ? UnitAttr::get(
context.getContext())
1948 if (fn.flags & slang::ast::MethodFlags::Pure) {
1950 SmallVector<Type, 1> extraParams;
1952 mlir::FlatSymbolRefAttr::get(classLowering.
op.getSymNameAttr());
1954 moore::ClassHandleType::get(
context.getContext(), classSym);
1955 extraParams.push_back(handleTy);
1959 mlir::emitError(loc) <<
"Invalid function signature for " << fn.name;
1963 moore::ClassMethodDeclOp::create(builder, loc, fn.name, funcTy,
nullptr);
1967 auto *lowering =
context.declareFunction(fn);
1971 if (failed(
context.convertFunction(fn)))
1974 if (!lowering->capturesFinalized)
1982 FunctionType fnTy = lowering->op.getFunctionType();
1984 moore::ClassMethodDeclOp::create(builder, loc, fn.name, fnTy,
1985 SymbolRefAttr::get(lowering->op));
2002 LogicalResult visit(
const slang::ast::MethodPrototypeSymbol &fn) {
2003 const auto *externImpl = fn.getSubroutine();
2007 <<
"Didn't find an implementation matching the forward declaration "
2012 return visit(*externImpl);
2016 LogicalResult visit(
const slang::ast::ClassType &cls) {
2017 if (failed(
context.buildClassProperties(cls)))
2019 return context.materializeClassMethods(cls);
2023 template <
typename T>
2024 LogicalResult visit(T &&node) {
2025 Location loc = UnknownLoc::get(
context.getContext());
2026 if constexpr (
requires { node.location; })
2028 mlir::emitError(loc) <<
"unsupported construct in ClassType members: "
2029 << slang::ast::toString(node.kind);
2037 auto &lowering =
classes[&cls];
2039 return lowering.get();
2040 lowering = std::make_unique<ClassLowering>();
2045 OpBuilder::InsertionGuard g(
builder);
2050 builder.setInsertionPoint(it->second);
2052 auto symName = fullyQualifiedClassName(*
this, cls);
2054 auto [base, impls] = buildBaseAndImplementsAttrs(*
this, cls);
2056 moore::ClassDeclOp::create(
builder, loc, symName, base, impls);
2058 SymbolTable::setSymbolVisibility(classDeclOp,
2059 SymbolTable::Visibility::Public);
2061 lowering->op = classDeclOp;
2064 return lowering.get();
2071 timeScale = classdecl.getTimeScale().value_or(slang::TimeScale());
2072 llvm::scope_exit timeScaleGuard([&] {
timeScale = prevTimeScale; });
2079 if (classdecl.getBaseClass()) {
2080 if (
const auto *baseClassDecl =
2081 classdecl.getBaseClass()->as_if<slang::ast::ClassType>()) {
2092 return ClassPropertyVisitor(*
this, *lowering).run(classdecl);
2099 timeScale = classdecl.getTimeScale().value_or(slang::TimeScale());
2100 llvm::scope_exit timeScaleGuard([&] {
timeScale = prevTimeScale; });
2103 auto it =
classes.find(&classdecl);
2104 if (it ==
classes.end() || !it->second)
2108 if (classdecl.getBaseClass()) {
2109 if (
const auto *baseClassDecl =
2110 classdecl.getBaseClass()->as_if<slang::ast::ClassType>()) {
2116 return ClassMethodVisitor(*
this, *it->second).run(classdecl);
2126 OpBuilder::InsertionGuard g(
builder);
2131 builder.setInsertionPoint(it->second);
2135 SmallString<64> symName;
2139 if (
const auto *classVar = var.as_if<slang::ast::ClassPropertySymbol>()) {
2140 if (
const auto *parentScope = classVar->getParentScope()) {
2141 if (
const auto *parentClass =
2142 parentScope->asSymbol().as_if<slang::ast::ClassType>())
2143 symName = fullyQualifiedClassName(*
this, *parentClass);
2145 mlir::emitError(loc)
2146 <<
"Could not access parent class of class property "
2151 mlir::emitError(loc) <<
"Could not get parent scope of class property "
2156 symName += var.name;
2159 symName += var.name;
2168 auto varOp = moore::GlobalVariableOp::create(
builder, loc, symName,
2169 cast<moore::UnpackedType>(type));
2176 if (var.getInitializer())
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
static FIRRTLBaseType convertType(FIRRTLBaseType type)
Returns null type if no conversion is needed.
static Location convertLocation(MLIRContext *context, const slang::SourceManager &sourceManager, slang::SourceLocation loc)
Convert a slang SourceLocation to an MLIR Location.
static Location getLoc(DefSlot slot)
static moore::ProcedureKind convertProcedureKind(slang::ast::ProceduralBlockKind kind)
static FunctionType getFunctionSignature(Context &context, const slang::ast::SubroutineSymbol &subroutine, llvm::SmallVectorImpl< Type > &extraParams)
Helper function to generate the function signature from a SubroutineSymbol and optional extra argumen...
static void guessNamespacePrefix(const slang::ast::Symbol &symbol, SmallString< 64 > &prefix)
static LogicalResult rewriteCallSitesToPassCaptures(mlir::func::FuncOp callee, ArrayRef< Value > captures)
Special case handling for recursive functions with captures; this function fixes the in-body call of ...
static moore::NetKind convertNetKind(slang::ast::NetType::NetKind kind)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
int run(Type[Generator] generator=CppGenerator, cmdline_args=sys.argv)
bool debugInfo
Generate debug information in the form of debug dialect ops in the IR.
circt::moore::ClassDeclOp op
A helper class to facilitate the conversion from a Slang AST to MLIR operations.
LogicalResult convertFunction(const slang::ast::SubroutineSymbol &subroutine)
Convert a function.
FunctionLowering * declareCallableImpl(const slang::ast::SubroutineSymbol &subroutine, mlir::StringRef qualifiedName, llvm::SmallVectorImpl< Type > &extraParams)
Helper function to extract the commonalities in lowering of functions and methods.
ModuleLowering * convertModuleHeader(const slang::ast::InstanceBodySymbol *module)
Convert a module and its ports to an empty module op in the IR.
Value materializeConstant(const slang::ConstantValue &constant, const slang::ast::Type &type, Location loc)
Helper function to materialize a ConstantValue as an SSA value.
LogicalResult convertModuleBody(const slang::ast::InstanceBodySymbol *module)
Convert a module's body to the corresponding IR ops.
LogicalResult materializeClassMethods(const slang::ast::ClassType &classdecl)
DenseMap< const slang::ast::ValueSymbol *, moore::GlobalVariableOp > globalVariables
A table of defined global variables that may be referred to by name in expressions.
slang::ast::Compilation & compilation
OpBuilder builder
The builder used to create IR operations.
std::queue< const slang::ast::InstanceBodySymbol * > moduleWorklist
A list of modules for which the header has been created, but the body has not been converted yet.
LogicalResult convertGlobalVariable(const slang::ast::VariableSymbol &var)
Convert a variable to a moore.global_variable operation.
DenseMap< const slang::ast::ClassType *, std::unique_ptr< ClassLowering > > classes
Classes that have already been converted.
std::function< void(moore::ReadOp)> rvalueReadCallback
A listener called for every variable or net being read.
std::map< slang::SourceLocation, Operation * > orderedRootOps
The top-level operations ordered by their Slang source location.
Type convertType(const slang::ast::Type &type, LocationAttr loc={})
Convert a slang type into an MLIR type.
DenseMap< const slang::ast::SubroutineSymbol *, std::unique_ptr< FunctionLowering > > functions
Functions that have already been converted.
slang::TimeScale timeScale
The time scale currently in effect.
LogicalResult finalizeFunctionBodyCaptures(FunctionLowering &lowering)
ClassLowering * declareClass(const slang::ast::ClassType &cls)
ValueSymbols valueSymbols
std::function< void(mlir::Operation *)> variableAssignCallback
A listener called for every variable or net being assigned.
ValueSymbols::ScopeTy ValueSymbolScope
const ImportVerilogOptions & options
Value convertRvalueExpression(const slang::ast::Expression &expr, Type requiredType={})
LogicalResult traverseInstanceBody(const slang::ast::Symbol &symbol)
Value currentThisRef
Variable to track the value of the current function's implicit this reference.
InterfaceInstances::ScopeTy InterfaceInstanceScope
mlir::ModuleOp intoModuleOp
SymbolTable symbolTable
A symbol table of the MLIR module we are emitting into.
DenseMap< const slang::ast::InstanceBodySymbol *, SmallVector< HierPathInfo > > hierPaths
Collect all hierarchical names used for the per module/instance.
FunctionLowering * declareFunction(const slang::ast::SubroutineSymbol &subroutine)
Convert a function and its arguments to a function declaration in the IR.
InterfaceInstances interfaceInstances
LogicalResult buildClassProperties(const slang::ast::ClassType &classdecl)
LogicalResult convertPackage(const slang::ast::PackageSymbol &package)
Convert a package and its contents.
MLIRContext * getContext()
Return the MLIR context.
LogicalResult convertStatement(const slang::ast::Statement &stmt)
SmallVector< const slang::ast::ValueSymbol * > globalVariableWorklist
A list of global variables that still need their initializers to be converted.
DenseMap< const slang::ast::InstanceBodySymbol *, std::unique_ptr< ModuleLowering > > modules
How we have lowered modules to MLIR.
Location convertLocation(slang::SourceLocation loc)
Convert a slang SourceLocation into an MLIR Location.
Function lowering information.
llvm::DenseMap< Value, unsigned > captureIndex
llvm::SmallVector< Value, 4 > captures
Module lowering information.