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
55 changes: 37 additions & 18 deletions xls/codegen/testdata/assertions_comb_multiple_ifdef_guards.svtxt
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,45 @@ module assertions_top(
input wire [31:0] y,
output wire [31:0] out
);
wire [30:0] add_197;
wire ult_204;
wire [31:0] literal_202;
wire [30:0] add_211;
wire ult_208;
wire nand_213;
wire nand_214;
assign add_197 = y[31:1] + 31'h7fff_fffb;
assign ult_204 = y < 32'h0000_0014;
assign literal_202 = 32'h0000_0004;
assign add_211 = y[31:1] + 31'h0000_000f;
assign ult_208 = y < 32'h0000_000a;
assign nand_213 = ~(y > 32'h0000_0009 & ult_204 & {add_197, y[0]} > literal_202);
assign nand_214 = ~(ult_208 & y > literal_202);
assign out = ult_208 ? {add_211, y[0]} : y & {32{ult_204}};
function automatic [30:0] priority_sel_31b_2way (input reg [1:0] sel, input reg [30:0] case0, input reg [30:0] case1, input reg [30:0] default_value);
begin
unique casez (sel)
2'b?1: begin
priority_sel_31b_2way = case0;
end
2'b10: begin
priority_sel_31b_2way = case1;
end
2'b00: begin
priority_sel_31b_2way = default_value;
end
default: begin
// Propagate X
priority_sel_31b_2way = 'X;
end
endcase
end
endfunction
wire [30:0] add_189;
wire ult_196;
wire ult_197;
wire [31:0] literal_193;
wire [30:0] add_203;
wire nand_206;
wire nand_207;
assign add_189 = y[31:1] + 31'h7fff_fffb;
assign ult_196 = y < 32'h0000_0014;
assign ult_197 = y < 32'h0000_000a;
assign literal_193 = 32'h0000_0004;
assign add_203 = y[31:1] + 31'h0000_000f;
assign nand_206 = ~(ult_197 & y > literal_193);
assign nand_207 = ~(ult_196 & y > 32'h0000_0009 & {add_189, y[0]} > literal_193);
assign out = {priority_sel_31b_2way({ult_196, ult_197}, add_203, y[31:1], 31'h0000_0000), ult_196 & y[0]};
`ifdef ASSERT_ON
`ifndef SYNTHESIS
y_ge_than_21: assert final ($isunknown(ult_204) || ult_204) else $fatal(0, "Assertion failure via fail! @ xls/examples/assertions/assertions.x:32:14-32:37");
__assertions__main_0___itok__assertions__main___itok__assertions__main_0___itok__assertions__func_0__32_x_less_than_5: assert final ($isunknown(nand_213) || nand_213) else $fatal(0, "Assertion failure via assert! @ xls/examples/assertions/assertions.x:21:12-21:40");
__assertions__main_0___itok__assertions__main___itok__assertions__main_1___itok__assertions__func_0__32_x_less_than_5: assert final ($isunknown(nand_214) || nand_214) else $fatal(0, "Assertion failure via assert! @ xls/examples/assertions/assertions.x:21:12-21:40");
y_ge_than_21: assert final ($isunknown(ult_196) || ult_196) else $fatal(0, "Assertion failure via fail! @ xls/examples/assertions/assertions.x:32:14-32:37");
__assertions__main_0___itok__assertions__main___itok__assertions__main_0___itok__assertions__func_0__32_x_less_than_5: assert final ($isunknown(nand_206) || nand_206) else $fatal(0, "Assertion failure via assert! @ xls/examples/assertions/assertions.x:21:12-21:40");
__assertions__main_0___itok__assertions__main___itok__assertions__main_1___itok__assertions__func_0__32_x_less_than_5: assert final ($isunknown(nand_207) || nand_207) else $fatal(0, "Assertion failure via assert! @ xls/examples/assertions/assertions.x:21:12-21:40");
`endif // SYNTHESIS
`endif // ASSERT_ON
endmodule
55 changes: 37 additions & 18 deletions xls/codegen/testdata/assertions_comb_no_ifdef_guards.svtxt
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,41 @@ module assertions_top(
input wire [31:0] y,
output wire [31:0] out
);
wire [30:0] add_197;
wire ult_204;
wire [31:0] literal_202;
wire [30:0] add_211;
wire ult_208;
wire nand_213;
wire nand_214;
assign add_197 = y[31:1] + 31'h7fff_fffb;
assign ult_204 = y < 32'h0000_0014;
assign literal_202 = 32'h0000_0004;
assign add_211 = y[31:1] + 31'h0000_000f;
assign ult_208 = y < 32'h0000_000a;
assign nand_213 = ~(y > 32'h0000_0009 & ult_204 & {add_197, y[0]} > literal_202);
assign nand_214 = ~(ult_208 & y > literal_202);
assign out = ult_208 ? {add_211, y[0]} : y & {32{ult_204}};
y_ge_than_21: assert final ($isunknown(ult_204) || ult_204) else $fatal(0, "Assertion failure via fail! @ xls/examples/assertions/assertions.x:32:14-32:37");
__assertions__main_0___itok__assertions__main___itok__assertions__main_0___itok__assertions__func_0__32_x_less_than_5: assert final ($isunknown(nand_213) || nand_213) else $fatal(0, "Assertion failure via assert! @ xls/examples/assertions/assertions.x:21:12-21:40");
__assertions__main_0___itok__assertions__main___itok__assertions__main_1___itok__assertions__func_0__32_x_less_than_5: assert final ($isunknown(nand_214) || nand_214) else $fatal(0, "Assertion failure via assert! @ xls/examples/assertions/assertions.x:21:12-21:40");
function automatic [30:0] priority_sel_31b_2way (input reg [1:0] sel, input reg [30:0] case0, input reg [30:0] case1, input reg [30:0] default_value);
begin
unique casez (sel)
2'b?1: begin
priority_sel_31b_2way = case0;
end
2'b10: begin
priority_sel_31b_2way = case1;
end
2'b00: begin
priority_sel_31b_2way = default_value;
end
default: begin
// Propagate X
priority_sel_31b_2way = 'X;
end
endcase
end
endfunction
wire [30:0] add_189;
wire ult_196;
wire ult_197;
wire [31:0] literal_193;
wire [30:0] add_203;
wire nand_206;
wire nand_207;
assign add_189 = y[31:1] + 31'h7fff_fffb;
assign ult_196 = y < 32'h0000_0014;
assign ult_197 = y < 32'h0000_000a;
assign literal_193 = 32'h0000_0004;
assign add_203 = y[31:1] + 31'h0000_000f;
assign nand_206 = ~(ult_197 & y > literal_193);
assign nand_207 = ~(ult_196 & y > 32'h0000_0009 & {add_189, y[0]} > literal_193);
assign out = {priority_sel_31b_2way({ult_196, ult_197}, add_203, y[31:1], 31'h0000_0000), ult_196 & y[0]};
y_ge_than_21: assert final ($isunknown(ult_196) || ult_196) else $fatal(0, "Assertion failure via fail! @ xls/examples/assertions/assertions.x:32:14-32:37");
__assertions__main_0___itok__assertions__main___itok__assertions__main_0___itok__assertions__func_0__32_x_less_than_5: assert final ($isunknown(nand_206) || nand_206) else $fatal(0, "Assertion failure via assert! @ xls/examples/assertions/assertions.x:21:12-21:40");
__assertions__main_0___itok__assertions__main___itok__assertions__main_1___itok__assertions__func_0__32_x_less_than_5: assert final ($isunknown(nand_207) || nand_207) else $fatal(0, "Assertion failure via assert! @ xls/examples/assertions/assertions.x:21:12-21:40");
endmodule
1 change: 1 addition & 0 deletions xls/dslx/ir_convert/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ cc_library(
"//xls/ir:value_utils",
"//xls/ir:verifier",
"//xls/ir:xls_ir_interface_cc_proto",
"@com_google_absl//absl/algorithm:container",
"@com_google_absl//absl/container:btree",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
Expand Down
73 changes: 73 additions & 0 deletions xls/dslx/ir_convert/function_converter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <variant>
#include <vector>

#include "absl/algorithm/container.h"
#include "absl/container/btree_set.h"
#include "absl/container/flat_hash_map.h"
#include "absl/log/check.h"
Expand Down Expand Up @@ -4129,7 +4130,79 @@ absl::Status FunctionConverter::HandleStatement(const Statement* node) {
return absl::OkStatus();
}

absl::Status FunctionConverter::HandleConditionalChain(
const Conditional* node) {
XLS_RET_CHECK(std::holds_alternative<Conditional*>(node->alternate()));

std::vector<BValue> tests;
std::vector<BValue> results;
const Conditional* cond = node;
std::optional<BValue> higher_priority_true = std::nullopt;
while (true) {
XLS_RETURN_IF_ERROR(Visit(cond->test()));
XLS_ASSIGN_OR_RETURN(BValue test, Use(cond->test()));
{
ScopedControlPredicate scp(
this, [&](const PredicateFun& orig_control_predicate) {
BValue activated = orig_control_predicate();
CHECK_EQ(activated.GetType()->AsBitsOrDie()->bit_count(), 1);
if (higher_priority_true.has_value()) {
return function_builder_->And(
{activated, test,
function_builder_->Not(*higher_priority_true)});
} else {
return function_builder_->And(activated, test);
}
});
XLS_RETURN_IF_ERROR(Visit(cond->consequent()));
}
XLS_ASSIGN_OR_RETURN(BValue result, Use(cond->consequent()));
tests.push_back(test);
results.push_back(result);

if (higher_priority_true.has_value()) {
higher_priority_true = function_builder_->Or(*higher_priority_true, test);
} else {
higher_priority_true = test;
}

if (!std::holds_alternative<Conditional*>(cond->alternate())) {
break;
}
cond = std::get<Conditional*>(cond->alternate());
};

// We finished the final conditional in the chain, so what's left in the
// alternate is what we return if none of the tests are true.
{
ScopedControlPredicate scp(
this, [&](const PredicateFun& orig_control_predicate) {
BValue activated = orig_control_predicate();
CHECK_EQ(activated.GetType()->AsBitsOrDie()->bit_count(), 1);
return function_builder_->And(
activated, function_builder_->Not(*higher_priority_true));
});
XLS_RETURN_IF_ERROR(Visit(ToExprNode(cond->alternate())));
}
XLS_ASSIGN_OR_RETURN(BValue default_result,
Use(ToExprNode(cond->alternate())));

// Reverse the tests, since priority-select goes in LSB-first order.
absl::c_reverse(tests);
Def(node, [&](const SourceInfo& loc) -> BValue {
BValue selector = function_builder_->Concat(tests, loc);
return function_builder_->PrioritySelect(
selector, /*cases=*/results, /*default_value=*/default_result, loc);
});
return absl::OkStatus();
}

absl::Status FunctionConverter::HandleConditional(const Conditional* node) {
if (std::holds_alternative<Conditional*>(node->alternate())) {
// This is a chained conditional.
return HandleConditionalChain(node);
}

XLS_RETURN_IF_ERROR(Visit(node->test()));
XLS_ASSIGN_OR_RETURN(BValue arg0, Use(node->test()));

Expand Down
3 changes: 3 additions & 0 deletions xls/dslx/ir_convert/function_converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,9 @@ class FunctionConverter {
absl::Status HandleConditional(const Conditional* node);
absl::Status HandleTupleIndex(const TupleIndex* node);

// Handles a conditional chain (where the alternate is another conditional).
absl::Status HandleConditionalChain(const Conditional* node);

// Handles invocation of a user-defined function (UDF).
absl::Status HandleUdfInvocation(const Invocation* node, xls::Function* f,
std::vector<BValue> args);
Expand Down