[ImportVerilog] Add case statement.

This commit is contained in:
angel 2024-04-18 14:29:23 +08:00 committed by Hailong Sun
parent 80c6602d37
commit e2b0f3230b
2 changed files with 104 additions and 0 deletions

View File

@ -110,6 +110,59 @@ struct StmtVisitor {
return success(); return success();
} }
// Handle case statements.
LogicalResult visit(const slang::ast::CaseStatement &caseStmt) {
auto caseExpr = context.convertExpression(caseStmt.expr);
auto items = caseStmt.items;
// Used to generate the condition of the default case statement.
SmallVector<Value> defaultConds;
// Traverse the case items.
for (auto item : items) {
// One statement will be matched with multi-conditions.
// Like case(cond) 0, 1 : y = x; endcase.
SmallVector<Value> allConds;
for (const auto *expr : item.expressions) {
auto itemExpr = context.convertExpression(*expr);
auto newEqOp = builder.create<moore::EqOp>(loc, caseExpr, itemExpr);
allConds.push_back(newEqOp);
}
// Bound all conditions of an item into one.
auto cond = allConds.back();
allConds.pop_back();
while (!allConds.empty()) {
cond = builder.create<moore::OrOp>(loc, allConds.back(), cond);
allConds.pop_back();
}
// Gather all items' conditions.
defaultConds.push_back(cond);
cond =
builder.create<moore::ConversionOp>(loc, builder.getI1Type(), cond);
auto ifOp = builder.create<mlir::scf::IfOp>(loc, cond);
OpBuilder::InsertionGuard guard(builder);
builder.setInsertionPoint(ifOp.thenYield());
if (failed(context.convertStatement(*item.stmt)))
return failure();
}
// Handle the 'default case' statement if it exists.
if (caseStmt.defaultCase) {
auto cond = defaultConds.back();
defaultConds.pop_back();
while (!defaultConds.empty()) {
cond = builder.create<moore::OrOp>(loc, defaultConds.back(), cond);
defaultConds.pop_back();
}
cond = builder.create<moore::NotOp>(loc, cond);
cond =
builder.create<moore::ConversionOp>(loc, builder.getI1Type(), cond);
auto ifOp = builder.create<mlir::scf::IfOp>(loc, cond);
OpBuilder::InsertionGuard guard(builder);
builder.setInsertionPoint(ifOp.thenYield());
if (failed(context.convertStatement(*caseStmt.defaultCase)))
return failure();
}
return success();
}
// Handle `for` loops. // Handle `for` loops.
LogicalResult visit(const slang::ast::ForLoopStatement &stmt) { LogicalResult visit(const slang::ast::ForLoopStatement &stmt) {
if (!stmt.loopVars.empty()) if (!stmt.loopVars.empty())

View File

@ -129,6 +129,57 @@ module Statements;
x = z; x = z;
end end
//===------------------------------------------------------------------===//
// Case statements
// CHECK: [[TMP1:%.+]] = moore.eq %x, %x : !moore.bit -> !moore.bit
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.bit -> i1
// CHECK: scf.if [[TMP2]] {
// CHECK: moore.blocking_assign %x, %x : !moore.bit
// CHECK: }
// CHECK: [[TMP3:%.+]] = moore.eq %x, %x : !moore.bit -> !moore.bit
// CHECK: [[TMP4:%.+]] = moore.eq %x, %y : !moore.bit -> !moore.bit
// CHECK: [[TMP5:%.+]] = moore.or [[TMP3]], [[TMP4]] : !moore.bit
// CHECK: [[TMP6:%.+]] = moore.conversion [[TMP5]] : !moore.bit -> i1
// CHECK: scf.if [[TMP6]] {
// CHECK: moore.blocking_assign %x, %y : !moore.bit
// CHECK: }
case (x)
x: x = x;
x, y: x = y;
endcase
// CHECK: [[TMP1:%.+]] = moore.eq %x, %x : !moore.bit -> !moore.bit
// CHECK: [[TMP2:%.+]] = moore.conversion [[TMP1]] : !moore.bit -> i1
// CHECK: scf.if [[TMP2]] {
// CHECK: moore.blocking_assign %x, %x : !moore.bit
// CHECK: }
// CHECK: [[TMP3:%.+]] = moore.eq %x, %x : !moore.bit -> !moore.bit
// CHECK: [[TMP4:%.+]] = moore.eq %x, %y : !moore.bit -> !moore.bit
// CHECK: [[TMP5:%.+]] = moore.or [[TMP3]], [[TMP4]] : !moore.bit
// CHECK: [[TMP6:%.+]] = moore.conversion [[TMP5]] : !moore.bit -> i1
// CHECK: scf.if [[TMP6]] {
// CHECK: moore.blocking_assign %x, %y : !moore.bit
// CHECK: }
// CHECK: [[TMP7:%.+]] = moore.eq %x, %z : !moore.bit -> !moore.bit
// CHECK: [[TMP8:%.+]] = moore.conversion [[TMP7]] : !moore.bit -> i1
// CHECK: scf.if [[TMP8]] {
// CHECK: moore.blocking_assign %x, %z : !moore.bit
// CHECK: }
// CHECK: [[TMP9:%.+]] = moore.or [[TMP5]], [[TMP7]] : !moore.bit
// CHECK: [[TMP10:%.+]] = moore.or [[TMP1]], [[TMP9]] : !moore.bit
// CHECK: [[TMP11:%.+]] = moore.not [[TMP10]] : !moore.bit
// CHECK: [[TMP12:%.+]] = moore.conversion [[TMP11]] : !moore.bit -> i1
// CHECK: scf.if [[TMP12]] {
// CHECK: moore.blocking_assign %x, %x : !moore.bit
// CHECK: }
case (x)
x: x = x;
x, y: x = y;
z: x = z;
default x = x;
endcase
//===------------------------------------------------------------------===// //===------------------------------------------------------------------===//
// Loop statements // Loop statements