10 #include "slang/ast/Compilation.h"
12 using namespace circt;
13 using namespace ImportVerilog;
19 static moore::ProcedureKind
22 case slang::ast::ProceduralBlockKind::Always:
23 return moore::ProcedureKind::Always;
24 case slang::ast::ProceduralBlockKind::AlwaysComb:
25 return moore::ProcedureKind::AlwaysComb;
26 case slang::ast::ProceduralBlockKind::AlwaysLatch:
27 return moore::ProcedureKind::AlwaysLatch;
28 case slang::ast::ProceduralBlockKind::AlwaysFF:
29 return moore::ProcedureKind::AlwaysFF;
30 case slang::ast::ProceduralBlockKind::Initial:
31 return moore::ProcedureKind::Initial;
32 case slang::ast::ProceduralBlockKind::Final:
33 return moore::ProcedureKind::Final;
35 llvm_unreachable(
"all procedure kinds handled");
40 case slang::ast::NetType::Supply0:
41 return moore::NetKind::Supply0;
42 case slang::ast::NetType::Supply1:
43 return moore::NetKind::Supply1;
44 case slang::ast::NetType::Tri:
45 return moore::NetKind::Tri;
46 case slang::ast::NetType::TriAnd:
47 return moore::NetKind::TriAnd;
48 case slang::ast::NetType::TriOr:
49 return moore::NetKind::TriOr;
50 case slang::ast::NetType::TriReg:
51 return moore::NetKind::TriReg;
52 case slang::ast::NetType::Tri0:
53 return moore::NetKind::Tri0;
54 case slang::ast::NetType::Tri1:
55 return moore::NetKind::Tri1;
56 case slang::ast::NetType::UWire:
57 return moore::NetKind::UWire;
58 case slang::ast::NetType::Wire:
59 return moore::NetKind::Wire;
60 case slang::ast::NetType::WAnd:
61 return moore::NetKind::WAnd;
62 case slang::ast::NetType::WOr:
63 return moore::NetKind::WOr;
64 case slang::ast::NetType::Interconnect:
65 return moore::NetKind::Interconnect;
66 case slang::ast::NetType::UserDefined:
67 return moore::NetKind::UserDefined;
68 case slang::ast::NetType::Unknown:
69 return moore::NetKind::Unknown;
71 llvm_unreachable(
"all net kinds handled");
75 struct MemberVisitor {
80 MemberVisitor(
Context &context, Location loc)
84 LogicalResult visit(
const slang::ast::EmptyMemberSymbol &) {
90 LogicalResult visit(
const slang::ast::TransparentMemberSymbol &) {
95 LogicalResult visit(
const slang::ast::TypeAliasType &) {
return success(); }
98 LogicalResult visit(
const slang::ast::InstanceSymbol &instNode) {
103 builder.create<moore::InstanceOp>(
104 loc,
builder.getStringAttr(instNode.name),
111 LogicalResult visit(
const slang::ast::VariableSymbol &varNode) {
112 auto loweredType = context.
convertType(*varNode.getDeclaredType());
117 if (
const auto *init = varNode.getInitializer()) {
122 if (initial.getType() != loweredType)
124 builder.create<moore::ConversionOp>(loc, loweredType, initial);
127 auto varOp =
builder.create<moore::VariableOp>(
128 loc, loweredType,
builder.getStringAttr(varNode.name), initial);
134 LogicalResult visit(
const slang::ast::NetSymbol &netNode) {
135 auto loweredType = context.
convertType(*netNode.getDeclaredType());
140 if (netNode.getInitializer()) {
147 if (netkind == moore::NetKind::Interconnect ||
148 netkind == moore::NetKind::UserDefined ||
149 netkind == moore::NetKind::Unknown)
150 return mlir::emitError(loc,
"unsupported net kind `")
151 << netNode.netType.name <<
"`";
153 auto netOp =
builder.create<moore::NetOp>(
154 loc, loweredType,
builder.getStringAttr(netNode.name), netkind,
161 LogicalResult visit(
const slang::ast::ContinuousAssignSymbol &assignNode) {
162 if (
const auto *delay = assignNode.getDelay()) {
164 return mlir::emitError(loc,
165 "delayed continuous assignments not supported");
169 assignNode.getAssignment().as<slang::ast::AssignmentExpression>();
176 if (lhs.getType() != rhs.getType())
177 rhs =
builder.create<moore::ConversionOp>(loc, lhs.getType(), rhs);
179 builder.create<moore::ContinuousAssignOp>(loc, lhs, rhs);
184 LogicalResult visit(
const slang::ast::ProceduralBlockSymbol &procNode) {
185 auto procOp =
builder.create<moore::ProcedureOp>(
187 procOp.getBodyRegion().emplaceBlock();
188 OpBuilder::InsertionGuard guard(
builder);
189 builder.setInsertionPointToEnd(procOp.getBody());
200 LogicalResult visit(
const slang::ast::StatementBlockSymbol &) {
205 template <
typename T>
206 LogicalResult visit(T &&node) {
207 mlir::emitError(loc,
"unsupported construct: ")
222 const auto &root = compilation.getRoot();
227 for (
auto *unit : root.compilationUnits) {
228 for (
const auto &member : unit->members()) {
231 return mlir::emitError(loc,
"unsupported construct: ")
237 SmallVector<const slang::ast::InstanceSymbol *> topInstances;
238 for (
auto *inst : root.topInstances)
261 OpBuilder::InsertionGuard g(
builder);
266 if (module->getDefinition().definitionKind !=
267 slang::ast::DefinitionKind::Module) {
268 mlir::emitError(loc,
"unsupported construct: ")
269 << module->getDefinition().getKindString();
274 for (
auto *symbol : module->getPortList()) {
276 mlir::emitError(portLoc,
"unsupported module port: ")
287 builder.setInsertionPoint(it->second);
290 auto moduleOp =
builder.create<moore::SVModuleOp>(loc, module->name);
292 moduleOp.getBodyRegion().emplaceBlock();
308 auto moduleOp =
moduleOps.lookup(module);
310 OpBuilder::InsertionGuard g(
builder);
311 builder.setInsertionPointToEnd(moduleOp.getBody());
314 for (
auto &member : module->members()) {
316 if (failed(member.visit(MemberVisitor(*
this, loc))))
assert(baseType &&"element must be base type")
constexpr const char * toString(Flow flow)
static moore::ProcedureKind convertProcedureKind(slang::ast::ProceduralBlockKind kind)
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.
A helper class to facilitate the conversion from a Slang AST to MLIR operations.
LogicalResult convertModuleBody(const slang::ast::InstanceBodySymbol *module)
Convert a module's body to the corresponding IR ops.
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 convertCompilation(slang::ast::Compilation &compilation)
Convert hierarchy and structure AST nodes to MLIR ops.
Value convertExpression(const slang::ast::Expression &expr)
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::InstanceBodySymbol *, moore::SVModuleOp > moduleOps
How we have lowered modules to MLIR.
ValueSymbols valueSymbols
moore::SVModuleOp convertModuleHeader(const slang::ast::InstanceBodySymbol *module)
Convert a module and its ports to an empty module op in the IR.
ValueSymbols::ScopeTy ValueSymbolScope
mlir::ModuleOp intoModuleOp
SymbolTable symbolTable
A symbol table of the MLIR module we are emitting into.
LogicalResult convertStatement(const slang::ast::Statement &stmt)
Location convertLocation(slang::SourceLocation loc)
Convert a slang SourceLocation into an MLIR Location.