12 using namespace circt;
13 using namespace ImportVerilog;
26 LogicalResult visit(
const slang::ast::EmptyStatement &) {
return success(); }
35 LogicalResult visit(
const slang::ast::StatementList &stmts) {
36 for (
auto *stmt : stmts.list)
43 LogicalResult visit(
const slang::ast::BlockStatement &stmt) {
48 LogicalResult visit(
const slang::ast::ExpressionStatement &stmt) {
53 LogicalResult visit(
const slang::ast::VariableDeclStatement &stmt) {
54 const auto &var = stmt.symbol;
55 auto type = context.
convertType(*var.getDeclaredType());
60 if (
const auto *init = var.getInitializer()) {
67 auto varOp =
builder.create<moore::VariableOp>(
68 loc, type,
builder.getStringAttr(var.name), initial);
75 LogicalResult visit(
const slang::ast::ConditionalStatement &stmt) {
79 for (
const auto &condition : stmt.conditions) {
80 if (condition.pattern)
81 return mlir::emitError(loc,
82 "match patterns in if conditions not supported");
86 cond =
builder.createOrFold<moore::BoolCastOp>(loc, cond);
88 allConds =
builder.create<moore::AndOp>(loc, allConds, cond);
92 assert(allConds &&
"slang guarantees at least one condition");
94 builder.create<moore::ConversionOp>(loc,
builder.getI1Type(), allConds);
98 builder.create<scf::IfOp>(loc, allConds, stmt.ifFalse !=
nullptr);
99 OpBuilder::InsertionGuard guard(
builder);
102 builder.setInsertionPoint(ifOp.thenYield());
108 builder.setInsertionPoint(ifOp.elseYield());
117 LogicalResult visit(
const slang::ast::CaseStatement &caseStmt) {
119 auto items = caseStmt.items;
121 SmallVector<Value> defaultConds;
123 for (
auto item : items) {
126 SmallVector<Value> allConds;
127 for (
const auto *expr : item.expressions) {
129 auto newEqOp =
builder.create<moore::EqOp>(loc, caseExpr, itemExpr);
130 allConds.push_back(newEqOp);
133 auto cond = allConds.back();
135 while (!allConds.empty()) {
136 cond =
builder.create<moore::OrOp>(loc, allConds.back(), cond);
140 defaultConds.push_back(cond);
142 builder.create<moore::ConversionOp>(loc,
builder.getI1Type(), cond);
143 auto ifOp =
builder.create<mlir::scf::IfOp>(loc, cond);
144 OpBuilder::InsertionGuard guard(
builder);
145 builder.setInsertionPoint(ifOp.thenYield());
150 if (caseStmt.defaultCase) {
151 auto cond = defaultConds.back();
152 defaultConds.pop_back();
153 while (!defaultConds.empty()) {
154 cond =
builder.create<moore::OrOp>(loc, defaultConds.back(), cond);
155 defaultConds.pop_back();
157 cond =
builder.create<moore::NotOp>(loc, cond);
159 builder.create<moore::ConversionOp>(loc,
builder.getI1Type(), cond);
160 auto ifOp =
builder.create<mlir::scf::IfOp>(loc, cond);
161 OpBuilder::InsertionGuard guard(
builder);
162 builder.setInsertionPoint(ifOp.thenYield());
170 LogicalResult visit(
const slang::ast::ForLoopStatement &stmt) {
171 if (!stmt.loopVars.empty())
172 return mlir::emitError(loc,
173 "variables in for loop initializer not supported");
176 for (
auto *initExpr : stmt.initializers)
181 auto whileOp =
builder.create<scf::WhileOp>(loc, TypeRange{}, ValueRange{});
182 OpBuilder::InsertionGuard guard(
builder);
185 builder.createBlock(&whileOp.getBefore());
189 cond =
builder.createOrFold<moore::BoolCastOp>(loc, cond);
190 cond =
builder.create<moore::ConversionOp>(loc,
builder.getI1Type(), cond);
191 builder.create<mlir::scf::ConditionOp>(loc, cond, ValueRange{});
194 builder.createBlock(&whileOp.getAfter());
197 for (
auto *stepExpr : stmt.steps)
200 builder.create<mlir::scf::YieldOp>(loc);
206 LogicalResult visit(
const slang::ast::RepeatLoopStatement &stmt) {
212 auto type = cast<moore::IntType>(count.getType());
213 auto whileOp =
builder.create<scf::WhileOp>(loc, type, count);
214 OpBuilder::InsertionGuard guard(
builder);
217 auto *block =
builder.createBlock(&whileOp.getBefore(), {}, type, loc);
218 auto counterArg = block->getArgument(0);
219 auto cond =
builder.createOrFold<moore::BoolCastOp>(loc, counterArg);
220 cond =
builder.create<moore::ConversionOp>(loc,
builder.getI1Type(), cond);
221 builder.create<scf::ConditionOp>(loc, cond, counterArg);
224 block =
builder.createBlock(&whileOp.getAfter(), {}, type, loc);
227 counterArg = block->getArgument(0);
228 auto constOne =
builder.create<moore::ConstantOp>(loc, type, 1);
229 auto subOp =
builder.create<moore::SubOp>(loc, counterArg, constOne);
230 builder.create<scf::YieldOp>(loc, ValueRange{subOp});
236 LogicalResult visit(
const slang::ast::WhileLoopStatement &stmt) {
238 auto whileOp =
builder.create<scf::WhileOp>(loc, TypeRange{}, ValueRange{});
239 OpBuilder::InsertionGuard guard(
builder);
242 builder.createBlock(&whileOp.getBefore());
246 cond =
builder.createOrFold<moore::BoolCastOp>(loc, cond);
247 cond =
builder.create<moore::ConversionOp>(loc,
builder.getI1Type(), cond);
248 builder.create<mlir::scf::ConditionOp>(loc, cond, ValueRange{});
251 builder.createBlock(&whileOp.getAfter());
254 builder.create<mlir::scf::YieldOp>(loc);
260 LogicalResult visit(
const slang::ast::DoWhileLoopStatement &stmt) {
262 auto whileOp =
builder.create<scf::WhileOp>(loc, TypeRange{}, ValueRange{});
263 OpBuilder::InsertionGuard guard(
builder);
267 builder.createBlock(&whileOp.getBefore());
273 cond =
builder.createOrFold<moore::BoolCastOp>(loc, cond);
274 cond =
builder.create<moore::ConversionOp>(loc,
builder.getI1Type(), cond);
275 builder.create<mlir::scf::ConditionOp>(loc, cond, ValueRange{});
278 builder.createBlock(&whileOp.getAfter());
279 builder.create<mlir::scf::YieldOp>(loc);
285 LogicalResult visit(
const slang::ast::ForeverLoopStatement &stmt) {
287 auto whileOp =
builder.create<scf::WhileOp>(loc, TypeRange{}, ValueRange{});
288 OpBuilder::InsertionGuard guard(
builder);
291 builder.createBlock(&whileOp.getBefore());
293 builder.create<mlir::scf::ConditionOp>(loc, cond, ValueRange{});
296 builder.createBlock(&whileOp.getAfter());
299 builder.create<mlir::scf::YieldOp>(loc);
305 LogicalResult visit(
const slang::ast::TimedStatement &stmt) {
310 template <
typename T>
311 LogicalResult visit(T &&stmt) {
312 mlir::emitError(loc,
"unsupported statement: ")
314 return mlir::failure();
317 LogicalResult visitInvalid(
const slang::ast::Statement &stmt) {
318 mlir::emitError(loc,
"invalid statement: ")
320 return mlir::failure();
325 LogicalResult Context::convertStatement(
const slang::ast::Statement &stmt) {
assert(baseType &&"element must be base type")
constexpr const char * toString(Flow flow)
static Location convertLocation(MLIRContext *context, const slang::SourceManager &sourceManager, SmallDenseMap< slang::BufferID, StringRef > &bufferFilePaths, slang::SourceLocation loc)
Convert a slang SourceLocation to an MLIR Location.
This helps visit TypeOp nodes.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
A helper class to facilitate the conversion from a Slang AST to MLIR operations.
Value convertExpression(const slang::ast::Expression &expr)
Type convertType(const slang::ast::Type &type, LocationAttr loc={})
Convert a slang type into an MLIR type.
ValueSymbols valueSymbols
LogicalResult convertStatement(const slang::ast::Statement &stmt)