forked from llvm/circt
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[SV] Introduce a new SV dialect with operations that provide access to
if/ifdef/always @ posedge, fwrite, and macro expressions. This is still very simple and early on, but is a reasonable starting point to expand the capabilities for the verilog printer.
- Loading branch information
Showing
17 changed files
with
393 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
add_mlir_dialect(SV sv) | ||
|
||
set(LLVM_TARGET_DEFINITIONS SV.td) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
//===- SV/IR/Dialect.h - SV dialect declaration -----------------*- C++ -*-===// | ||
// | ||
// This file defines an SV MLIR dialect. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef CIRCT_DIALECT_SV_DIALECT_H | ||
#define CIRCT_DIALECT_SV_DIALECT_H | ||
|
||
#include "mlir/IR/Dialect.h" | ||
|
||
namespace circt { | ||
namespace sv { | ||
using namespace mlir; | ||
|
||
class SVDialect : public Dialect { | ||
public: | ||
explicit SVDialect(MLIRContext *context); | ||
~SVDialect(); | ||
|
||
static StringRef getDialectNamespace() { return "sv"; } | ||
}; | ||
|
||
} // namespace sv | ||
} // namespace circt | ||
|
||
#endif // CIRCT_DIALECT_SV_DIALECT_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
//===- Expressions.td - SV expression ops ------------------*- tablegen -*-===// | ||
// | ||
// This describes the ops for SystemVerilog expressions. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
def TextualValueOp : SVOp<"textual_value", [NoSideEffect]> { | ||
let summary = "Expression that expands to a value given SystemVerilog text"; | ||
let description = [{ | ||
This operation produces a typed value expressed by a string of | ||
SystemVerilog. This can be used to access macros and other values that are | ||
only sensible as Verilog text. | ||
|
||
The text string is expected to have the highest precedence, so it should | ||
be parenthesized if it isn't a single token. | ||
}]; | ||
|
||
let arguments = (ins StrAttr:$string); | ||
let results = (outs AnySignlessInteger:$result); | ||
|
||
let assemblyFormat = [{ | ||
$string attr-dict `:` type($result) | ||
}]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
//===- SV/Ops.h - Declare SV dialect operations -----------------*- C++ -*-===// | ||
// | ||
// This file declares the operation classes for the SV dialect. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef CIRCT_DIALECT_SV_OPS_H | ||
#define CIRCT_DIALECT_SV_OPS_H | ||
|
||
#include "circt/Dialect/SV/Dialect.h" | ||
#include "mlir/IR/OpImplementation.h" | ||
#include "mlir/Interfaces/SideEffectInterfaces.h" | ||
|
||
namespace circt { | ||
namespace sv { | ||
|
||
#define GET_OP_CLASSES | ||
#include "circt/Dialect/SV/SV.h.inc" | ||
|
||
} // namespace sv | ||
} // namespace circt | ||
|
||
#endif // CIRCT_DIALECT_SV_OPS_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
//===- SV.td - SystemVerilog dialect definition ------------*- tablegen -*-===// | ||
// | ||
// This is the top level file for the SV dialect. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef SV_TD | ||
#define SV_TD | ||
|
||
include "mlir/IR/OpBase.td" | ||
include "mlir/Interfaces/SideEffectInterfaces.td" | ||
|
||
def SVDialect : Dialect { | ||
let name = "sv"; | ||
|
||
let summary = "Types and operations for SV dialect"; | ||
let description = [{ | ||
This dialect defines the `sv` dialect, which represents various | ||
SystemVerilog-specific constructs in an AST-like representation. | ||
}]; | ||
|
||
let cppNamespace = "sv"; | ||
} | ||
|
||
// Base class for the operation in this dialect. | ||
class SVOp<string mnemonic, list<OpTrait> traits = []> : | ||
Op<SVDialect, mnemonic, traits>; | ||
|
||
include "Expressions.td" | ||
include "Statements.td" | ||
|
||
#endif // SV_TD |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
//===- Statements.td - SV statements ops -------------------*- tablegen -*-===// | ||
// | ||
// This describes the ops for System Verilog statements. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
class HasCustomParserPrinter { | ||
code printer = [{ return ::print$cppClass(p, *this); }]; | ||
code parser = [{ return ::parse$cppClass(parser, result); }]; | ||
} | ||
|
||
def HasRegionTerminator : SingleBlockImplicitTerminator<"YieldOp">; | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Control flow like-operations | ||
//===----------------------------------------------------------------------===// | ||
|
||
def IfDefOp : SVOp<"ifdef", [HasRegionTerminator]>, HasCustomParserPrinter { | ||
let summary = "'ifdef MACRO' block"; | ||
|
||
let description = [{ | ||
This operation is an #ifdef block, or an #ifndef block if `string` starts | ||
with a `!` character. | ||
}]; | ||
|
||
let regions = (region SizedRegion<1>:$body); | ||
let arguments = (ins StrAttr:$cond); | ||
let results = (outs); | ||
|
||
// TODO: ODS doesn't support parsing/printing regions yet :-( | ||
// let assemblyFormat = [{ $clock attr-dict $body }];*/ | ||
} | ||
|
||
def IfOp : SVOp<"if", [HasRegionTerminator]>, | ||
HasCustomParserPrinter { | ||
let summary = "'if (cond)' block"; | ||
|
||
let regions = (region SizedRegion<1>:$body); | ||
let arguments = (ins I1:$cond); | ||
let results = (outs); | ||
|
||
// TODO: ODS doesn't support parsing/printing regions yet :-( | ||
//let assemblyFormat = [{ $cond attr-dict $body }]; | ||
} | ||
|
||
// TODO: This should be generalized, e.g. with an enum to specify the edge | ||
// trigger behavior. | ||
def AlwaysAtPosEdgeOp : SVOp<"alwaysat_posedge", [HasRegionTerminator]>, | ||
HasCustomParserPrinter { | ||
let summary = "'always @(posedge ...)'' block"; | ||
|
||
let regions = (region SizedRegion<1>:$body); | ||
let arguments = (ins I1:$clock); | ||
let results = (outs); | ||
|
||
// TODO: ODS doesn't support parsing/printing regions yet :-( | ||
//let assemblyFormat = [{ $clock attr-dict $body }]; | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Other Statements | ||
//===----------------------------------------------------------------------===// | ||
|
||
def YieldOp | ||
: SVOp<"yield", [NoSideEffect, Terminator, | ||
ParentOneOf<["IfDefOp, IfOp", "AlwaysAtPosEdgeOp"]>]> { | ||
let summary = "terminator for control-flow operation regions"; | ||
let arguments = (ins); | ||
|
||
let assemblyFormat = [{attr-dict}]; | ||
} | ||
|
||
// TODO: This needs to model the file descriptor to write on as well as the | ||
// arguments. | ||
def FWriteOp : SVOp<"fwrite", []> { | ||
let summary = "'$fwrite' statement"; | ||
|
||
let arguments = (ins StrAttr:$string); | ||
let results = (outs); | ||
|
||
let assemblyFormat = [{ | ||
$string attr-dict | ||
}]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
file(GLOB globbed *.cpp) | ||
add_mlir_dialect_library(MLIRSV | ||
${globbed} | ||
|
||
ADDITIONAL_HEADER_DIRS | ||
${CIRCT_MAIN_INCLUDE_DIR}/circt/Dialect/SV | ||
|
||
DEPENDS | ||
MLIRSVIncGen | ||
|
||
LINK_COMPONENTS | ||
Support | ||
|
||
LINK_LIBS PUBLIC | ||
) | ||
|
||
add_dependencies(mlir-headers MLIRSVIncGen) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
//===- Dialect.cpp - Implement the SV dialect -----------------------------===// | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "circt/Dialect/SV/Dialect.h" | ||
#include "circt/Dialect/SV/Ops.h" | ||
|
||
using namespace circt; | ||
using namespace sv; | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Dialect specification. | ||
//===----------------------------------------------------------------------===// | ||
|
||
SVDialect::SVDialect(MLIRContext *context) | ||
: Dialect(getDialectNamespace(), context) { | ||
|
||
// Register operations. | ||
addOperations< | ||
#define GET_OP_LIST | ||
#include "circt/Dialect/SV/SV.cpp.inc" | ||
>(); | ||
} | ||
|
||
SVDialect::~SVDialect() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
//===- Ops.cpp - Implement the SV operations ------------------------------===// | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "circt/Dialect/SV/Ops.h" | ||
#include "mlir/IR/Builders.h" | ||
#include "mlir/IR/StandardTypes.h" | ||
|
||
using namespace circt; | ||
using namespace sv; | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Control flow like-operations | ||
//===----------------------------------------------------------------------===// | ||
|
||
//===----------------------------------------------------------------------===// | ||
// IfDefOp | ||
|
||
static ParseResult parseIfDefOp(OpAsmParser &parser, OperationState &result) { | ||
StringAttr cond; | ||
Region *body = result.addRegion(); | ||
if (parser.parseAttribute(cond, "cond", result.attributes) || | ||
parser.parseRegion(*body, llvm::None, llvm::None) || | ||
parser.parseOptionalAttrDict(result.attributes)) | ||
return failure(); | ||
|
||
IfDefOp::ensureTerminator(*body, parser.getBuilder(), result.location); | ||
return success(); | ||
} | ||
|
||
static void printIfDefOp(OpAsmPrinter &p, IfDefOp op) { | ||
p << op.getOperationName() << ' '; | ||
p.printAttribute(op.condAttr()); | ||
p.printRegion(op.body(), | ||
/*printEntryBlockArgs=*/false, | ||
/*printBlockTerminators=*/false); | ||
p.printOptionalAttrDict(op.getAttrs(), {"cond"}); | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// IfOp | ||
|
||
static ParseResult parseIfOp(OpAsmParser &parser, OperationState &result) { | ||
OpAsmParser::OperandType cond; | ||
Region *body = result.addRegion(); | ||
if (parser.parseOperand(cond) || | ||
parser.resolveOperand(cond, parser.getBuilder().getI1Type(), | ||
result.operands) || | ||
parser.parseRegion(*body, llvm::None, llvm::None) || | ||
parser.parseOptionalAttrDict(result.attributes)) | ||
return failure(); | ||
|
||
IfOp::ensureTerminator(*body, parser.getBuilder(), result.location); | ||
return success(); | ||
} | ||
|
||
static void printIfOp(OpAsmPrinter &p, IfOp op) { | ||
p << op.getOperationName() << ' ' << op.cond(); | ||
p.printRegion(op.body(), | ||
/*printEntryBlockArgs=*/false, | ||
/*printBlockTerminators=*/false); | ||
p.printOptionalAttrDict(op.getAttrs()); | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// AlwaysAtPosEdgeOp | ||
|
||
static ParseResult parseAlwaysAtPosEdgeOp(OpAsmParser &parser, | ||
OperationState &result) { | ||
OpAsmParser::OperandType clock; | ||
Region *body = result.addRegion(); | ||
if (parser.parseOperand(clock) || | ||
parser.resolveOperand(clock, parser.getBuilder().getI1Type(), | ||
result.operands) || | ||
parser.parseRegion(*body, llvm::None, llvm::None) || | ||
parser.parseOptionalAttrDict(result.attributes)) | ||
return failure(); | ||
|
||
AlwaysAtPosEdgeOp::ensureTerminator(*body, parser.getBuilder(), | ||
result.location); | ||
return success(); | ||
} | ||
|
||
static void printAlwaysAtPosEdgeOp(OpAsmPrinter &p, AlwaysAtPosEdgeOp op) { | ||
p << op.getOperationName() << ' ' << op.clock(); | ||
p.printRegion(op.body(), | ||
/*printEntryBlockArgs=*/false, | ||
/*printBlockTerminators=*/false); | ||
p.printOptionalAttrDict(op.getAttrs()); | ||
} | ||
|
||
//===----------------------------------------------------------------------===// | ||
// TableGen generated logic. | ||
//===----------------------------------------------------------------------===// | ||
|
||
// Provide the autogenerated implementation guts for the Op classes. | ||
#define GET_OP_CLASSES | ||
#include "circt/Dialect/SV/SV.cpp.inc" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,5 @@ add_mlir_library(CIRCTEmitVerilog | |
LINK_LIBS PUBLIC | ||
MLIRFIRRTL | ||
MLIRRTL | ||
MLIRSV | ||
) |
Oops, something went wrong.