10#include "slang/ast/Compilation.h"
11#include "llvm/ADT/ScopeExit.h"
14using namespace ImportVerilog;
21 SmallString<64> &prefix) {
22 if (symbol.kind != slang::ast::SymbolKind::Package)
25 if (!symbol.name.empty()) {
26 prefix += symbol.name;
43 BaseVisitor(
Context &context, Location loc)
44 : context(context), loc(loc), builder(context.builder) {}
47 LogicalResult visit(
const slang::ast::EmptyMemberSymbol &) {
53 LogicalResult visit(
const slang::ast::TransparentMemberSymbol &) {
58 LogicalResult visit(
const slang::ast::TypeAliasType &) {
return success(); }
59 LogicalResult visit(
const slang::ast::ForwardingTypedefSymbol &) {
64 LogicalResult visit(
const slang::ast::ExplicitImportSymbol &) {
67 LogicalResult visit(
const slang::ast::WildcardImportSymbol &) {
72 LogicalResult visit(
const slang::ast::TypeParameterSymbol &) {
77 LogicalResult visit(
const slang::ast::ElabSystemTaskSymbol &) {
82 LogicalResult visit(
const slang::ast::ParameterSymbol ¶m) {
83 visitParameter(param);
87 LogicalResult visit(
const slang::ast::SpecparamSymbol ¶m) {
88 visitParameter(param);
93 void visitParameter(
const Node ¶m) {
103 if (builder.getInsertionBlock()->getParentOp() == context.
intoModuleOp)
104 context.
orderedRootOps.insert({param.location, value.getDefiningOp()});
108 SmallString<64> paramName;
110 paramName += param.name;
112 debug::VariableOp::create(builder, loc, builder.getStringAttr(paramName),
123struct RootVisitor :
public BaseVisitor {
124 using BaseVisitor::BaseVisitor;
125 using BaseVisitor::visit;
128 LogicalResult visit(
const slang::ast::PackageSymbol &package) {
133 LogicalResult visit(
const slang::ast::SubroutineSymbol &subroutine) {
138 template <
typename T>
139 LogicalResult visit(T &&node) {
140 mlir::emitError(loc,
"unsupported construct: ")
141 << slang::ast::toString(node.kind);
152struct PackageVisitor :
public BaseVisitor {
153 using BaseVisitor::BaseVisitor;
154 using BaseVisitor::visit;
157 LogicalResult visit(
const slang::ast::SubroutineSymbol &subroutine) {
162 template <
typename T>
163 LogicalResult visit(T &&node) {
164 mlir::emitError(loc,
"unsupported package member: ")
165 << slang::ast::toString(node.kind);
175static moore::ProcedureKind
178 case slang::ast::ProceduralBlockKind::Always:
179 return moore::ProcedureKind::Always;
180 case slang::ast::ProceduralBlockKind::AlwaysComb:
181 return moore::ProcedureKind::AlwaysComb;
182 case slang::ast::ProceduralBlockKind::AlwaysLatch:
183 return moore::ProcedureKind::AlwaysLatch;
184 case slang::ast::ProceduralBlockKind::AlwaysFF:
185 return moore::ProcedureKind::AlwaysFF;
186 case slang::ast::ProceduralBlockKind::Initial:
187 return moore::ProcedureKind::Initial;
188 case slang::ast::ProceduralBlockKind::Final:
189 return moore::ProcedureKind::Final;
191 llvm_unreachable(
"all procedure kinds handled");
196 case slang::ast::NetType::Supply0:
197 return moore::NetKind::Supply0;
198 case slang::ast::NetType::Supply1:
199 return moore::NetKind::Supply1;
200 case slang::ast::NetType::Tri:
201 return moore::NetKind::Tri;
202 case slang::ast::NetType::TriAnd:
203 return moore::NetKind::TriAnd;
204 case slang::ast::NetType::TriOr:
205 return moore::NetKind::TriOr;
206 case slang::ast::NetType::TriReg:
207 return moore::NetKind::TriReg;
208 case slang::ast::NetType::Tri0:
209 return moore::NetKind::Tri0;
210 case slang::ast::NetType::Tri1:
211 return moore::NetKind::Tri1;
212 case slang::ast::NetType::UWire:
213 return moore::NetKind::UWire;
214 case slang::ast::NetType::Wire:
215 return moore::NetKind::Wire;
216 case slang::ast::NetType::WAnd:
217 return moore::NetKind::WAnd;
218 case slang::ast::NetType::WOr:
219 return moore::NetKind::WOr;
220 case slang::ast::NetType::Interconnect:
221 return moore::NetKind::Interconnect;
222 case slang::ast::NetType::UserDefined:
223 return moore::NetKind::UserDefined;
224 case slang::ast::NetType::Unknown:
225 return moore::NetKind::Unknown;
227 llvm_unreachable(
"all net kinds handled");
231struct ModuleVisitor :
public BaseVisitor {
232 using BaseVisitor::visit;
236 StringRef blockNamePrefix;
238 ModuleVisitor(
Context &context, Location loc, StringRef blockNamePrefix =
"")
239 : BaseVisitor(context, loc), blockNamePrefix(blockNamePrefix) {}
242 LogicalResult visit(
const slang::ast::PortSymbol &) {
return success(); }
243 LogicalResult visit(
const slang::ast::MultiPortSymbol &) {
return success(); }
246 LogicalResult visit(
const slang::ast::GenvarSymbol &genvarNode) {
251 LogicalResult visit(
const slang::ast::DefParamSymbol &) {
return success(); }
255 LogicalResult visit(
const slang::ast::TypeParameterSymbol &) {
260 LogicalResult visit(
const slang::ast::InstanceSymbol &instNode) {
261 using slang::ast::ArgumentDirection;
262 using slang::ast::AssignmentExpression;
263 using slang::ast::MultiPortSymbol;
264 using slang::ast::PortSymbol;
269 auto module = moduleLowering->op;
270 auto moduleType =
module.getModuleType();
273 SymbolTable::setSymbolVisibility(module, SymbolTable::Visibility::Private);
280 portValues.reserve(moduleType.getNumPorts());
282 for (
const auto *con : instNode.getPortConnections()) {
283 const auto *expr = con->getExpression();
288 auto *port = con->port.as_if<PortSymbol>();
289 if (
auto *existingPort =
290 moduleLowering->portsBySyntaxNode.lookup(port->getSyntax()))
293 switch (port->direction) {
294 case ArgumentDirection::In: {
295 auto refType = moore::RefType::get(
296 cast<moore::UnpackedType>(context.
convertType(port->getType())));
298 if (
const auto *net =
299 port->internalSymbol->as_if<slang::ast::NetSymbol>()) {
300 auto netOp = moore::NetOp::create(
301 builder, loc, refType,
302 StringAttr::get(builder.getContext(), net->name),
304 auto readOp = moore::ReadOp::create(builder, loc, netOp);
305 portValues.insert({port, readOp});
306 }
else if (
const auto *var =
308 ->as_if<slang::ast::VariableSymbol>()) {
309 auto varOp = moore::VariableOp::create(
310 builder, loc, refType,
311 StringAttr::get(builder.getContext(), var->name),
nullptr);
312 auto readOp = moore::ReadOp::create(builder, loc, varOp);
313 portValues.insert({port, readOp});
315 return mlir::emitError(loc)
316 <<
"unsupported internal symbol for unconnected port `"
317 << port->name <<
"`";
324 case ArgumentDirection::Out:
329 return mlir::emitError(loc)
330 <<
"unsupported port `" << port->name <<
"` ("
331 << slang::ast::toString(port->kind) <<
")";
337 if (
const auto *assign = expr->as_if<AssignmentExpression>())
338 expr = &assign->left();
343 if (
auto *port = con->port.as_if<PortSymbol>()) {
345 auto value = (port->direction == ArgumentDirection::In)
350 if (
auto *existingPort =
351 moduleLowering->portsBySyntaxNode.lookup(con->port.getSyntax()))
353 portValues.insert({port, value});
360 if (
const auto *multiPort = con->port.as_if<MultiPortSymbol>()) {
366 for (
const auto *port :
llvm::reverse(multiPort->ports)) {
367 if (
auto *existingPort = moduleLowering->portsBySyntaxNode.lookup(
368 con->port.getSyntax()))
370 unsigned width = port->getType().getBitWidth();
371 auto sliceType = context.
convertType(port->getType());
374 Value slice = moore::ExtractRefOp::create(
376 moore::RefType::get(cast<moore::UnpackedType>(sliceType)), value,
379 if (port->direction == ArgumentDirection::In)
380 slice = moore::ReadOp::create(builder, loc, slice);
381 portValues.insert({port, slice});
387 mlir::emitError(loc) <<
"unsupported instance port `" << con->port.name
388 <<
"` (" << slang::ast::toString(con->port.kind)
394 SmallVector<Value> inputValues;
395 SmallVector<Value> outputValues;
396 inputValues.reserve(moduleType.getNumInputs());
397 outputValues.reserve(moduleType.getNumOutputs());
399 for (
auto &port : moduleLowering->ports) {
400 auto value = portValues.lookup(&port.ast);
401 if (port.ast.direction == ArgumentDirection::Out)
402 outputValues.push_back(value);
404 inputValues.push_back(value);
408 for (
auto [value, type] :
409 llvm::zip(inputValues, moduleType.getInputTypes()))
411 value = context.materializeConversion(type, value, false, value.
getLoc());
415 for (
const auto &hierPath : context.hierPaths[&instNode.body])
416 if (auto hierValue = context.valueSymbols.lookup(hierPath.valueSym);
417 hierPath.hierName && hierPath.direction == ArgumentDirection::In)
418 inputValues.push_back(hierValue);
421 auto inputNames = builder.getArrayAttr(moduleType.getInputNames());
422 auto outputNames = builder.getArrayAttr(moduleType.getOutputNames());
423 auto inst = moore::InstanceOp::create(
424 builder, loc, moduleType.getOutputTypes(),
425 builder.getStringAttr(Twine(blockNamePrefix) + instNode.name),
426 FlatSymbolRefAttr::get(module.getSymNameAttr()), inputValues,
427 inputNames, outputNames);
430 for (
const auto &hierPath : context.hierPaths[&instNode.body])
431 if (hierPath.idx && hierPath.direction == ArgumentDirection::
Out)
432 context.valueSymbols.insert(hierPath.valueSym,
433 inst->getResult(*hierPath.idx));
436 for (
auto [lvalue, output] :
llvm::zip(outputValues, inst.getOutputs())) {
439 Value rvalue = output;
440 auto dstType = cast<moore::RefType>(lvalue.getType()).getNestedType();
443 moore::ContinuousAssignOp::create(builder, loc, lvalue, rvalue);
450 LogicalResult visit(
const slang::ast::VariableSymbol &varNode) {
451 auto loweredType = context.
convertType(*varNode.getDeclaredType());
456 if (
const auto *init = varNode.getInitializer()) {
462 auto varOp = moore::VariableOp::create(
464 moore::RefType::get(cast<moore::UnpackedType>(loweredType)),
465 builder.getStringAttr(Twine(blockNamePrefix) + varNode.name), initial);
471 LogicalResult visit(
const slang::ast::NetSymbol &netNode) {
472 auto loweredType = context.
convertType(*netNode.getDeclaredType());
477 if (
const auto *init = netNode.getInitializer()) {
484 if (netkind == moore::NetKind::Interconnect ||
485 netkind == moore::NetKind::UserDefined ||
486 netkind == moore::NetKind::Unknown)
487 return mlir::emitError(loc,
"unsupported net kind `")
488 << netNode.netType.name <<
"`";
490 auto netOp = moore::NetOp::create(
492 moore::RefType::get(cast<moore::UnpackedType>(loweredType)),
493 builder.getStringAttr(Twine(blockNamePrefix) + netNode.name), netkind,
500 LogicalResult visit(
const slang::ast::ContinuousAssignSymbol &assignNode) {
501 if (
const auto *delay = assignNode.getDelay()) {
503 return mlir::emitError(loc,
504 "delayed continuous assignments not supported");
508 assignNode.getAssignment().as<slang::ast::AssignmentExpression>();
514 expr.right(), cast<moore::RefType>(lhs.getType()).getNestedType());
518 moore::ContinuousAssignOp::create(builder, loc, lhs, rhs);
523 LogicalResult convertProcedure(moore::ProcedureKind kind,
524 const slang::ast::Statement &body) {
525 auto procOp = moore::ProcedureOp::create(builder, loc, kind);
526 OpBuilder::InsertionGuard guard(builder);
527 builder.setInsertionPointToEnd(&procOp.getBody().emplaceBlock());
531 if (builder.getBlock())
532 moore::ReturnOp::create(builder, loc);
536 LogicalResult visit(
const slang::ast::ProceduralBlockSymbol &procNode) {
540 auto *stmt = procNode.getBody().as_if<slang::ast::TimedStatement>();
541 if (procNode.procedureKind == slang::ast::ProceduralBlockKind::Always &&
543 stmt->timing.kind == slang::ast::TimingControlKind::ImplicitEvent)
544 return convertProcedure(moore::ProcedureKind::AlwaysComb, stmt->stmt);
552 LogicalResult visit(
const slang::ast::GenerateBlockSymbol &genNode) {
554 if (genNode.isUninstantiated)
558 SmallString<64> prefixBuffer;
559 auto prefix = blockNamePrefix;
560 if (!genNode.name.empty()) {
561 prefixBuffer += blockNamePrefix;
562 prefixBuffer += genNode.name;
564 prefix = prefixBuffer;
568 for (
auto &member : genNode.members())
569 if (failed(member.visit(ModuleVisitor(context, loc, prefix))))
575 LogicalResult visit(
const slang::ast::GenerateBlockArraySymbol &genArrNode) {
578 SmallString<64> prefixBuffer;
579 if (!genArrNode.name.empty()) {
580 prefixBuffer += blockNamePrefix;
581 prefixBuffer += genArrNode.name;
583 auto prefixBufferBaseLen = prefixBuffer.size();
586 for (
const auto *entry : genArrNode.entries) {
588 auto prefix = blockNamePrefix;
589 if (prefixBufferBaseLen > 0) {
590 prefixBuffer.resize(prefixBufferBaseLen);
592 if (entry->arrayIndex)
593 prefixBuffer += entry->arrayIndex->toString();
595 Twine(entry->constructIndex).toVector(prefixBuffer);
597 prefix = prefixBuffer;
601 if (failed(entry->asSymbol().visit(ModuleVisitor(context, loc, prefix))))
613 LogicalResult visit(
const slang::ast::StatementBlockSymbol &) {
619 LogicalResult visit(
const slang::ast::SequenceSymbol &seqNode) {
625 LogicalResult visit(
const slang::ast::PropertySymbol &propNode) {
630 LogicalResult visit(
const slang::ast::SubroutineSymbol &subroutine) {
635 template <
typename T>
636 LogicalResult visit(T &&node) {
637 mlir::emitError(loc,
"unsupported module member: ")
638 << slang::ast::toString(node.kind);
650LogicalResult Context::convertCompilation() {
656 timeScale = root.getTimeScale().value_or(slang::TimeScale());
657 auto timeScaleGuard =
658 llvm::make_scope_exit([&] {
timeScale = prevTimeScale; });
662 for (
auto *inst : root.topInstances)
669 for (
auto *unit : root.compilationUnits) {
670 for (
const auto &member : unit->members()) {
672 if (failed(member.visit(RootVisitor(*
this, loc))))
678 SmallVector<const slang::ast::InstanceSymbol *> topInstances;
679 for (
auto *inst : root.topInstances)
685 auto *
module = moduleWorklist.front();
700 using slang::ast::ArgumentDirection;
701 using slang::ast::MultiPortSymbol;
702 using slang::ast::ParameterSymbol;
703 using slang::ast::PortSymbol;
704 using slang::ast::TypeParameterSymbol;
709 timeScale =
module->getTimeScale().value_or(slang::TimeScale());
710 auto timeScaleGuard =
711 llvm::make_scope_exit([&] {
timeScale = prevTimeScale; });
713 auto parameters =
module->getParameters();
714 bool hasModuleSame =
false;
718 for (
auto const &existingModule :
modules) {
719 if (module->getDeclaringDefinition() ==
720 existingModule.getFirst()->getDeclaringDefinition()) {
721 auto moduleParameters = existingModule.getFirst()->getParameters();
722 hasModuleSame =
true;
723 for (
auto it1 = parameters.begin(), it2 = moduleParameters.begin();
724 it1 != parameters.end() && it2 != moduleParameters.end();
727 if (it1 == parameters.end() || it2 == moduleParameters.end()) {
728 hasModuleSame =
false;
731 const auto *para1 = (*it1)->symbol.as_if<ParameterSymbol>();
732 const auto *para2 = (*it2)->symbol.as_if<ParameterSymbol>();
734 if ((para1 ==
nullptr) ^ (para2 ==
nullptr)) {
735 hasModuleSame =
false;
739 if (para1 !=
nullptr) {
740 hasModuleSame = para1->getValue() == para2->getValue();
743 if (para1 ==
nullptr) {
745 (*it1)->symbol.as<TypeParameterSymbol>().getTypeAlias());
747 (*it2)->symbol.as<TypeParameterSymbol>().getTypeAlias());
748 hasModuleSame = para1Type == para2Type;
754 module = existingModule.first;
763 slot = std::make_unique<ModuleLowering>();
764 auto &lowering = *slot;
767 OpBuilder::InsertionGuard g(
builder);
772 if (module->getDefinition().definitionKind !=
773 slang::ast::DefinitionKind::Module) {
774 mlir::emitError(loc) <<
"unsupported definition: "
775 <<
module->getDefinition().getKindString();
780 auto block = std::make_unique<Block>();
781 SmallVector<hw::ModulePort> modulePorts;
784 unsigned int outputIdx = 0, inputIdx = 0;
785 for (
auto *symbol :
module->getPortList()) {
786 auto handlePort = [&](const PortSymbol &port) {
787 auto portLoc = convertLocation(port.location);
791 auto portName =
builder.getStringAttr(port.name);
793 if (port.direction == ArgumentDirection::Out) {
799 if (port.direction != ArgumentDirection::In)
800 type = moore::RefType::get(cast<moore::UnpackedType>(type));
802 arg = block->addArgument(type, portLoc);
805 lowering.ports.push_back({port, portLoc, arg});
809 if (
const auto *port = symbol->as_if<PortSymbol>()) {
810 if (failed(handlePort(*port)))
812 }
else if (
const auto *multiPort = symbol->as_if<MultiPortSymbol>()) {
813 for (
auto *port : multiPort->ports)
814 if (failed(handlePort(*port)))
818 <<
"unsupported module port `" << symbol->name <<
"` ("
819 << slang::ast::toString(symbol->kind) <<
")";
825 for (
auto &hierPath : hierPaths[module]) {
826 auto hierType =
convertType(hierPath.valueSym->getType());
830 if (
auto hierName = hierPath.hierName) {
832 hierType = moore::RefType::get(cast<moore::UnpackedType>(hierType));
833 if (hierPath.direction == ArgumentDirection::Out) {
834 hierPath.idx = outputIdx++;
837 hierPath.idx = inputIdx++;
840 block->addArgument(hierType, hierLoc);
844 auto moduleType = hw::ModuleType::get(getContext(), modulePorts);
848 auto it = orderedRootOps.upper_bound(module->location);
849 if (it == orderedRootOps.end())
850 builder.setInsertionPointToEnd(intoModuleOp.getBody());
852 builder.setInsertionPoint(it->second);
856 moore::SVModuleOp::create(builder, loc, module->name, moduleType);
857 orderedRootOps.insert(it, {
module->location, moduleOp});
858 moduleOp.getBodyRegion().push_back(block.release());
859 lowering.op = moduleOp;
863 symbolTable.insert(moduleOp);
866 moduleWorklist.push(module);
869 for (
const auto &port : lowering.ports)
870 lowering.portsBySyntaxNode.insert({port.ast.getSyntax(), &port.ast});
879 auto &lowering = *
modules[module];
880 OpBuilder::InsertionGuard g(
builder);
881 builder.setInsertionPointToEnd(lowering.op.getBody());
888 timeScale =
module->getTimeScale().value_or(slang::TimeScale());
889 auto timeScaleGuard =
890 llvm::make_scope_exit([&] {
timeScale = prevTimeScale; });
896 if (hierPath.direction == slang::ast::ArgumentDirection::In && hierPath.idx)
898 lowering.op.getBody()->getArgument(*hierPath.idx));
901 for (
auto &member :
module->members()) {
902 auto loc = convertLocation(member.location);
903 if (failed(member.visit(ModuleVisitor(*
this, loc))))
910 SmallVector<Value> outputs;
911 for (
auto &port : lowering.ports) {
913 if (
auto *expr = port.ast.getInternalExpr()) {
914 value = convertLvalueExpression(*expr);
915 }
else if (port.ast.internalSymbol) {
916 if (
const auto *sym =
917 port.ast.internalSymbol->as_if<slang::ast::ValueSymbol>())
918 value = valueSymbols.lookup(sym);
921 return mlir::emitError(port.loc,
"unsupported port: `")
923 <<
"` does not map to an internal symbol or expression";
926 if (port.ast.direction == slang::ast::ArgumentDirection::Out) {
927 if (isa<moore::RefType>(value.getType()))
928 value = moore::ReadOp::create(builder, value.getLoc(), value);
929 outputs.push_back(value);
935 Value portArg = port.arg;
936 if (port.ast.direction != slang::ast::ArgumentDirection::In)
937 portArg = moore::ReadOp::create(builder, port.loc, port.arg);
938 moore::ContinuousAssignOp::create(builder, port.loc, value, portArg);
943 for (
auto &hierPath : hierPaths[module])
944 if (auto hierValue = valueSymbols.lookup(hierPath.valueSym))
945 if (hierPath.direction == slang::ast::ArgumentDirection::
Out)
946 outputs.push_back(hierValue);
948 moore::OutputOp::create(builder, lowering.op.getLoc(), outputs);
958 timeScale = package.getTimeScale().value_or(slang::TimeScale());
959 auto timeScaleGuard =
960 llvm::make_scope_exit([&] {
timeScale = prevTimeScale; });
962 OpBuilder::InsertionGuard g(
builder);
965 for (
auto &member : package.members()) {
967 if (failed(member.visit(PackageVisitor(*
this, loc))))
977 using slang::ast::ArgumentDirection;
984 return lowering.get();
986 lowering = std::make_unique<FunctionLowering>();
991 OpBuilder::InsertionGuard g(
builder);
996 builder.setInsertionPoint(it->second);
999 if (subroutine.thisVar) {
1000 mlir::emitError(loc) <<
"unsupported class method";
1005 SmallVector<Type> inputTypes;
1006 SmallVector<Type, 1> outputTypes;
1008 for (
const auto *arg : subroutine.getArguments()) {
1012 if (arg->direction == ArgumentDirection::In) {
1013 inputTypes.push_back(type);
1015 inputTypes.push_back(
1016 moore::RefType::get(cast<moore::UnpackedType>(type)));
1020 if (!subroutine.getReturnType().isVoid()) {
1021 auto type =
convertType(subroutine.getReturnType());
1024 outputTypes.push_back(type);
1027 auto funcType = FunctionType::get(
getContext(), inputTypes, outputTypes);
1031 SmallString<64> funcName;
1033 funcName += subroutine.name;
1036 auto funcOp = mlir::func::FuncOp::create(
builder, loc, funcName, funcType);
1037 SymbolTable::setSymbolVisibility(funcOp, SymbolTable::Visibility::Private);
1039 lowering->op = funcOp;
1045 return lowering.get();
1054 timeScale = subroutine.getTimeScale().value_or(slang::TimeScale());
1055 auto timeScaleGuard =
1056 llvm::make_scope_exit([&] {
timeScale = prevTimeScale; });
1065 SmallVector<moore::VariableOp> argVariables;
1066 auto &block = lowering->op.getBody().emplaceBlock();
1067 for (
auto [astArg, type] :
1068 llvm::zip(subroutine.getArguments(),
1069 lowering->op.getFunctionType().getInputs())) {
1071 auto blockArg = block.addArgument(type, loc);
1073 if (isa<moore::RefType>(type)) {
1077 OpBuilder::InsertionGuard g(
builder);
1078 builder.setInsertionPointToEnd(&block);
1080 auto shadowArg = moore::VariableOp::create(
1081 builder, loc, moore::RefType::get(cast<moore::UnpackedType>(type)),
1082 StringAttr{}, blockArg);
1084 argVariables.push_back(shadowArg);
1089 OpBuilder::InsertionGuard g(
builder);
1090 builder.setInsertionPointToEnd(&block);
1093 if (subroutine.returnValVar) {
1094 auto type =
convertType(*subroutine.returnValVar->getDeclaredType());
1097 returnVar = moore::VariableOp::create(
1098 builder, lowering->op.getLoc(),
1099 moore::RefType::get(cast<moore::UnpackedType>(type)), StringAttr{},
1101 valueSymbols.insert(subroutine.returnValVar, returnVar);
1110 if (returnVar && !subroutine.getReturnType().isVoid()) {
1112 moore::ReadOp::create(
builder, returnVar.getLoc(), returnVar);
1113 mlir::func::ReturnOp::create(
builder, lowering->op.getLoc(), read);
1115 mlir::func::ReturnOp::create(
builder, lowering->op.getLoc(),
1119 if (returnVar && returnVar.use_empty())
1120 returnVar.getDefiningOp()->erase();
1122 for (
auto var : argVariables) {
1123 if (llvm::all_of(var->getUsers(),
1124 [](
auto *user) { return isa<moore::ReadOp>(user); })) {
1125 for (
auto *user : llvm::make_early_inc_range(var->getUsers())) {
1126 user->getResult(0).replaceAllUsesWith(var.getInitial());
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 void guessNamespacePrefix(const slang::ast::Symbol &symbol, SmallString< 64 > &prefix)
static moore::NetKind convertNetKind(slang::ast::NetType::NetKind kind)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
bool lowerAlwaysAtStarAsComb
Interpret always @(*) as always_comb.
bool debugInfo
Generate debug information in the form of debug dialect ops in the IR.
A helper class to facilitate the conversion from a Slang AST to MLIR operations.
LogicalResult convertFunction(const slang::ast::SubroutineSymbol &subroutine)
Convert a function.
Value materializeConversion(Type type, Value value, bool isSigned, Location loc)
Helper function to insert the necessary operations to cast a value from one type to another.
ModuleLowering * convertModuleHeader(const slang::ast::InstanceBodySymbol *module)
Convert a module and its ports to an empty module op in the IR.
Value convertLvalueExpression(const slang::ast::Expression &expr)
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.
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.
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.
ValueSymbols valueSymbols
ValueSymbols::ScopeTy ValueSymbolScope
const ImportVerilogOptions & options
Value convertRvalueExpression(const slang::ast::Expression &expr, Type requiredType={})
LogicalResult traverseInstanceBody(const slang::ast::Symbol &symbol)
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.
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)
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.
Module lowering information.