Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions xls/contrib/mlir/IR/xls_ops.td
Original file line number Diff line number Diff line change
Expand Up @@ -2349,6 +2349,29 @@ def Xls_AssertOp : Xls_Op<"assert"> {
}];
}

def Xls_CoverOp : Xls_Op<"cover"> {
let summary = "Records every time the condition evaluates to true";
let description = [{
Records the number of times the given condition evaluates to true. The label
uniquely identifies the coverage point within its scope of emission (though
uniqueness is not enforced by either the MLIR verifier or the XLS compiler).

The op has no return value, which is noteworthy for two reasons: (1) Unlike
`xls.assert`, `xls.cover` does not take a token input and does not produce a
token output. (2) In XLS IR, the op returns an empty tuple but does so only
because there is no other way to express "no return value" type. This design
is more idiomatic in MLIR, at the cost of a small structural difference from
XLS IR.
}];
let arguments = (ins
I1:$condition,
StrAttr:$label
);
let assemblyFormat = [{
$condition `,` $label attr-dict
}];
}

def Xls_GateOp :
Xls_Op<"gate", [
ShapesAreConsistent<["data", "result"]>,
Expand Down
10 changes: 10 additions & 0 deletions xls/contrib/mlir/testdata/translate_cover.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: xls_translate --mlir-xls-to-xls %s -- 2>&1 \
// RUN: | FileCheck %s --dump-input-filter=all

// CHECK-LABEL: top fn test_cover(
// CHECK-SAME: [[ARG0:.*]]: bits[1]
// CHECK: cover([[ARG0]], label="my_coverpoint"
func.func @test_cover(%arg0: i1) {
xls.cover %arg0, "my_coverpoint"
func.return
}
11 changes: 11 additions & 0 deletions xls/contrib/mlir/testdata/translate_from_xls/cover.ir
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// RUN: xls_translate --xls-to-mlir-xls %s 2>&1 | FileCheck %s

package translate_ops

// CHECK-LABEL: func @test_cover(
// CHECK-SAME: %[[COND:.*]]: i1)
fn test_cover(cond: bits[1] id=1) -> bits[1] {
// CHECK: xls.cover %[[COND]], "my_coverpoint"
cover.2: () = cover(cond, label="my_coverpoint", id=2)
ret not.3: bits[1] = not(cond, id=3)
}
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,11 @@ BValue convertOp(AssertOp op, const TranslationState& state, BuilderBase& fb) {
state.getLoc(op));
}

BValue convertOp(CoverOp op, const TranslationState& state, BuilderBase& fb) {
return fb.Cover(state.getXlsValue(op.getCondition()), op.getLabel(),
state.getLoc(op));
}

// Tuple operations
BValue convertOp(TupleOp op, const TranslationState& state, BuilderBase& fb) {
std::vector<BValue> values;
Expand Down Expand Up @@ -1208,7 +1213,7 @@ FailureOr<BValue> convertFunction(TranslationState& translation_state,
// Debugging ops
TraceOp,
// Misc. side-effecting ops
AssertOp, GateOp>(
AssertOp, CoverOp, GateOp>(
[&](auto t) { return convertOp(t, translation_state, fb); })
.Case<func::ReturnOp, YieldOp>([&](auto ret) {
if (ret.getNumOperands() == 1) {
Expand Down
31 changes: 26 additions & 5 deletions xls/contrib/mlir/tools/xls_translate/xls_translate_to_mlir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,22 @@ absl::StatusOr<Operation*> translateOp(::xls::Assert& node, OpBuilder& builder,
: nullptr);
}

absl::StatusOr<Operation*> translateOp(::xls::Cover& node, OpBuilder& builder,
TranslationState& state) {
auto condition = state.getMlirValue(node.condition()->id());
if (!condition.ok()) {
return condition.status();
}

auto loc = translateLoc(node.loc(), builder, state);
if (!loc.ok()) {
return loc.status();
}

return CoverOp::create(builder, *loc, *condition,
builder.getStringAttr(node.label()));
}

absl::StatusOr<Operation*> translateAnyOp(::xls::Node& xls_node,
OpBuilder& builder,
TranslationState& state) {
Expand Down Expand Up @@ -1402,8 +1418,9 @@ absl::StatusOr<Operation*> translateAnyOp(::xls::Node& xls_node,
"StateRead not handeled during proc translation.");
} else if (dynamic_cast<::xls::Next*>(&xls_node)) {
return absl::InternalError("Next not handeled during proc translation.");
} else if (dynamic_cast<::xls::Cover*>(&xls_node) ||
dynamic_cast<::xls::MinDelay*>(&xls_node)) {
} else if (auto* xls_op = dynamic_cast<::xls::Cover*>(&xls_node)) {
op = translateOp(*xls_op, builder, state);
} else if (dynamic_cast<::xls::MinDelay*>(&xls_node)) {
return absl::InternalError(absl::StrCat(
"Unsupported operation: ", ::xls::OpToString(xls_node.op()),
" - Not yet available in XLS MLIR!"));
Expand All @@ -1416,9 +1433,13 @@ absl::StatusOr<Operation*> translateAnyOp(::xls::Node& xls_node,
return op.status();
}

if (auto err = state.setMlirValue(xls_node.id(), (*op)->getResult(0));
!err.ok()) {
return err;
// Only map the result if the op produces one (e.g., xls.cover has no
// results).
if ((*op)->getNumResults() > 0) {
if (auto err = state.setMlirValue(xls_node.id(), (*op)->getResult(0));
!err.ok()) {
return err;
}
}

return *op;
Expand Down
Loading