mirror of https://github.com/llvm/circt.git
[ImportVerilog] Add full_case attribute support (#8762)
This patch adds support of `(* full_case *)` attribute in case statements [1], which says that all possible case items have been covered and no default clause is needed. [1]: http://www1.pldworld.com/@xilinx/html/technote/TOOL/MANUAL/21i_doc/data/fndtn/ver/ver7_4.htm
This commit is contained in:
parent
e80a67d30d
commit
9088c29f4b
|
@ -7,6 +7,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ImportVerilogInternals.h"
|
||||
#include "slang/ast/Compilation.h"
|
||||
#include "slang/ast/SystemSubroutine.h"
|
||||
#include "llvm/ADT/ScopeExit.h"
|
||||
|
||||
|
@ -258,6 +259,7 @@ struct StmtVisitor {
|
|||
|
||||
/// Handle case statements.
|
||||
LogicalResult visit(const slang::ast::CaseStatement &caseStmt) {
|
||||
using slang::ast::AttributeSymbol;
|
||||
using slang::ast::CaseStatementCondition;
|
||||
auto caseExpr = context.convertRvalueExpression(caseStmt.expr);
|
||||
if (!caseExpr)
|
||||
|
@ -335,6 +337,12 @@ struct StmtVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
const auto caseStmtAttrs = context.compilation.getAttributes(caseStmt);
|
||||
const bool hasFullCaseAttr =
|
||||
llvm::find_if(caseStmtAttrs, [](const AttributeSymbol *attr) {
|
||||
return attr->name == "full_case";
|
||||
}) != caseStmtAttrs.end();
|
||||
|
||||
// Check if the case statement looks exhaustive assuming two-state values.
|
||||
// We use this information to work around a common bug in input Verilog
|
||||
// where a case statement enumerates all possible two-state values of the
|
||||
|
@ -369,7 +377,13 @@ struct StmtVisitor {
|
|||
// If the case statement is exhaustive assuming two-state values, don't
|
||||
// generate the default case. Instead, branch to the last match block. This
|
||||
// will essentially make the last case item the "default".
|
||||
if (twoStateExhaustive && lastMatchBlock &&
|
||||
//
|
||||
// Alternatively, if the case statement has an (* full_case *) attribute
|
||||
// but no default case, it indicates that the developer has intentionally
|
||||
// covered all known possible values. Hence, the last match block is
|
||||
// treated as the implicit "default" case.
|
||||
if ((twoStateExhaustive || (hasFullCaseAttr && !caseStmt.defaultCase)) &&
|
||||
lastMatchBlock &&
|
||||
caseStmt.condition == CaseStatementCondition::Normal) {
|
||||
builder.create<mlir::cf::BranchOp>(loc, lastMatchBlock);
|
||||
} else {
|
||||
|
|
|
@ -2853,6 +2853,44 @@ function void seeminglyExhaustiveCase(logic [1:0] a);
|
|||
endcase
|
||||
endfunction
|
||||
|
||||
// Check that ImportVerilog recognizes case statements with (* full_case *)
|
||||
// attribute, assuming the case expression uses a two-state values (0 and 1).
|
||||
// The (* full_case *) attribute informs the synthesis tool that all possible
|
||||
// cases are explicitly covered, even without a default clause, thereby
|
||||
// preventing latch inference.
|
||||
// CHECK-LABEL: @verifyFullCaseSupport
|
||||
function void verifyFullCaseSupport(logic [1:0] a);
|
||||
// CHECK: [[Z:%.+]] = moore.variable
|
||||
logic [2:0] z;
|
||||
// CHECK: moore.constant 0 : i2
|
||||
// CHECK: cf.cond_br {{%.+}}, [[CASE0:\^.+]], [[ELSE0:\^.+]]
|
||||
(* full_case *)
|
||||
case (a)
|
||||
// CHECK: [[CASE0]]:
|
||||
// CHECK: moore.constant 1 : i3
|
||||
// CHECK: cf.br [[EXIT:\^.+]]
|
||||
2'd0: z = 3'b001;
|
||||
// CHECK: [[ELSE0]]:
|
||||
// CHECK: moore.constant 1 : i2
|
||||
// CHECK: cf.cond_br {{%.+}}, [[CASE1:\^.+]], [[ELSE1:\^.+]]
|
||||
// CHECK: [[CASE1]]:
|
||||
// CHECK: moore.constant 2 : i3
|
||||
// CHECK: cf.br [[EXIT]]
|
||||
2'd1: z = 3'b010;
|
||||
// CHECK: [[ELSE1]]:
|
||||
// CHECK: moore.constant -2 : i2
|
||||
// CHECK: cf.cond_br {{%.+}}, [[CASE2:\^.+]], [[ELSE2:\^.+]]
|
||||
// CHECK: [[CASE2]]:
|
||||
// CHECK: moore.constant -4 : i3
|
||||
// CHECK: cf.br [[EXIT]]
|
||||
2'd2: z = 3'b100;
|
||||
// Branch to the final item. This trivial basic block would be removed
|
||||
// later during CFG simplification.
|
||||
// CHECK: [[ELSE2]]:
|
||||
// CHECK-NEXT: cf.br [[CASE2]]
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
// Regression test for #8657.
|
||||
// CHECK-LABEL: rvalueAndLvalueElementSelect
|
||||
module rvalueAndLvalueElementSelect(
|
||||
|
|
Loading…
Reference in New Issue