diff --git a/xls/codegen/passes_ng/state_to_channel_conversion_pass_test.cc b/xls/codegen/passes_ng/state_to_channel_conversion_pass_test.cc index fe552716e9..abd6b1eac2 100644 --- a/xls/codegen/passes_ng/state_to_channel_conversion_pass_test.cc +++ b/xls/codegen/passes_ng/state_to_channel_conversion_pass_test.cc @@ -311,8 +311,9 @@ class CounterProcWithMaxHelper : public CounterProcHelper { uint32_t start_value, uint32_t delta_each_round) override { BValue enable = pb.StateElement("enable", Value(UBits(1, 1))); - BValue counter = pb.StateElement(kCounterStateElementName, - Value(UBits(start_value, 32)), enable); + BValue counter = + pb.StateElement(kCounterStateElementName, Value(UBits(start_value, 32)), + enable, /*non_synthesizable=*/false); pb.SendIf(out_channel, pb.Literal(Value::Token()), enable, counter); pb.Next(counter, pb.Add(counter, pb.Literal(UBits(delta_each_round, 32))), enable); diff --git a/xls/codegen/register_combining_pass_test.cc b/xls/codegen/register_combining_pass_test.cc index 11c957f893..858389be82 100644 --- a/xls/codegen/register_combining_pass_test.cc +++ b/xls/codegen/register_combining_pass_test.cc @@ -492,7 +492,8 @@ TEST_F(RegisterCombiningPassTest, DoesntApplyToPredicatedReads) { auto tok = pb.InitialToken(); auto always_false = pb.Literal(UBits(0, 1)); auto st = pb.StateElement("foo", UBits(1, 32), - /*read_predicate=*/always_false); + /*read_predicate=*/always_false, + /*non_synthesizable=*/false); auto lit_1 = pb.Literal(UBits(1, 32)); auto always_false_2 = pb.Literal(UBits(0, 1)); auto st_v = pb.Select(always_false_2, /*cases=*/{lit_1, st}); diff --git a/xls/codegen_v_1_5/convert_to_block_test.cc b/xls/codegen_v_1_5/convert_to_block_test.cc index 4d11d81c94..f5ddc7896c 100644 --- a/xls/codegen_v_1_5/convert_to_block_test.cc +++ b/xls/codegen_v_1_5/convert_to_block_test.cc @@ -77,7 +77,8 @@ TEST_F(ConvertToBlockTest, ProcWithExplicitStateAccessNextValueStateElement) { pb.AddOutputChannel("out_ch", p->GetBitsType(32))); XLS_ASSERT_OK_AND_ASSIGN(StateElement * se, - pb.UnreadStateElement("state", Value(UBits(0, 32)))); + pb.UnreadStateElement("state", Value(UBits(0, 32)), + /*non_synthesizable=*/false)); BValue state_read = pb.StateRead(se); BValue current = pb.Identity(state_read); BValue add_val = pb.Add(current, pb.Literal(UBits(1, 32))); diff --git a/xls/codegen_v_1_5/pipeline_register_insertion_pass_test.cc b/xls/codegen_v_1_5/pipeline_register_insertion_pass_test.cc index a6a765d3bc..c851a15432 100644 --- a/xls/codegen_v_1_5/pipeline_register_insertion_pass_test.cc +++ b/xls/codegen_v_1_5/pipeline_register_insertion_pass_test.cc @@ -889,7 +889,8 @@ TEST_F(PipelineRegisterInsertionPassTest, sbb.StartStage(sbb.Literal(UBits(1, 1)), sbb.Literal(UBits(1, 1))); XLS_ASSERT_OK_AND_ASSIGN( StateElement * source_se, - source->AppendUnreadStateElement("acc", Value(UBits(0, 32)))); + source->AppendUnreadStateElement("acc", Value(UBits(0, 32)), + /*non_synthesizable=*/false)); XLS_ASSERT_OK_AND_ASSIGN(StateRead * source_read, source->AddStateRead(source_se)); BValue acc = sbb.SourceNode(source_read); diff --git a/xls/contrib/xlscc/generate_fsm.cc b/xls/contrib/xlscc/generate_fsm.cc index 544a1d005a..e662ecf69f 100644 --- a/xls/contrib/xlscc/generate_fsm.cc +++ b/xls/contrib/xlscc/generate_fsm.cc @@ -992,9 +992,10 @@ NewFSMGenerator::GenerateNewFSMInvocation( pb.Literal(xls::ZeroOfType(top_return_type), body_loc)); } - TrackedBValue next_activation_slice_index = pb.StateElement( - "__next_activation_slice", - xls::Value(xls::UBits(0, num_slice_index_bits)), body_loc); + TrackedBValue next_activation_slice_index = + pb.StateElement("__next_activation_slice", + xls::Value(xls::UBits(0, num_slice_index_bits)), + /*non_synthesizable=*/false, body_loc); TrackedBValue first_slice_index = pb.Literal(xls::UBits(0, num_slice_index_bits), body_loc); @@ -1014,7 +1015,8 @@ NewFSMGenerator::GenerateNewFSMInvocation( TrackedBValue state_element = pb.StateElement(absl::StrFormat("__jump_state_%li", jump_slice_index), - xls::Value(xls::UBits(0, 1)), body_loc); + xls::Value(xls::UBits(0, 1)), + /*non_synthesizable=*/false, body_loc); state_element_by_jump_slice_index[jump_slice_index] = state_element; } @@ -1055,7 +1057,8 @@ NewFSMGenerator::GenerateNewFSMInvocation( if (state_element.existing_state_element == nullptr) { xls_state_element = pb.StateElement( - state_element.name, xls::ZeroOfType(state_element.type), body_loc); + state_element.name, xls::ZeroOfType(state_element.type), + /*non_synthesizable=*/false, body_loc); } else { xls::StateRead* state_read = pb.proc()->GetStateReadByStateElement( state_element.existing_state_element); diff --git a/xls/contrib/xlscc/translate_block.cc b/xls/contrib/xlscc/translate_block.cc index 7fc17253f5..754cd4e9d5 100644 --- a/xls/contrib/xlscc/translate_block.cc +++ b/xls/contrib/xlscc/translate_block.cc @@ -1075,7 +1075,7 @@ Translator::GenerateOldFSMInvocation(PreparedBlock& prepared, xls::Value initial_exited_last_activation = xls::Value(xls::UBits(1, 1)); changed_state_last_activation = pb.StateElement( absl::StrFormat("%s_exited_last_activation", fsm_prefix), - initial_exited_last_activation, body_loc); + initial_exited_last_activation, /*non_synthesizable=*/false, body_loc); } // Set up state with wrap-around, if needed @@ -1107,8 +1107,9 @@ Translator::GenerateOldFSMInvocation(PreparedBlock& prepared, initial_args_val}; xls::Value initial_state = xls::Value::Tuple(initial_state_elements); - state_read = pb.StateElement(absl::StrFormat("%s_state", fsm_prefix), - initial_state, body_loc); + state_read = + pb.StateElement(absl::StrFormat("%s_state", fsm_prefix), initial_state, + /*non_synthesizable=*/false, body_loc); state_index = pb.TupleIndex(state_read, /*idx=*/0, body_loc, /*name=*/absl::StrFormat("%s_state_index", fsm_prefix)); @@ -2092,7 +2093,8 @@ Translator::GenerateIRBlockPrepare( decl_leaf.leaf_index = i; } TrackedBValue elem_bval = - pb.StateElement(decomposed_name, decomposed_value, body_loc); + pb.StateElement(decomposed_name, decomposed_value, + /*non_synthesizable=*/false, body_loc); xls::StateElement* state_elem = elem_bval.node()->As()->state_element(); prepared.state_element_for_variable[decl_leaf] = state_elem; diff --git a/xls/contrib/xlscc/unit_tests/fsm_layout_test.cc b/xls/contrib/xlscc/unit_tests/fsm_layout_test.cc index daff4ae4e8..2d00a6624e 100644 --- a/xls/contrib/xlscc/unit_tests/fsm_layout_test.cc +++ b/xls/contrib/xlscc/unit_tests/fsm_layout_test.cc @@ -95,8 +95,9 @@ class FSMLayoutTest : public XlsccTestBase { DeclLeaf decl_leaf = {.decl = decl, .leaf_index = i}; const std::string& name = decl->getNameAsString(); std::string decomposed_name = absl::StrFormat("%s_%d", name, i); - NATIVE_BVAL state_read_bval = pb.StateElement( - decomposed_name, decomposed_value, xls::SourceInfo()); + NATIVE_BVAL state_read_bval = + pb.StateElement(decomposed_name, decomposed_value, + /*non_synthesizable=*/false, xls::SourceInfo()); state_element_for_static[decl_leaf] = state_read_bval.node()->As()->state_element(); } diff --git a/xls/dev_tools/extract_state_element.cc b/xls/dev_tools/extract_state_element.cc index 4c8d9f101c..aefe342477 100644 --- a/xls/dev_tools/extract_state_element.cc +++ b/xls/dev_tools/extract_state_element.cc @@ -163,7 +163,7 @@ absl::Status ExtractSegmentInto(ProcBuilder& pb, Proc* original, s->predicate() ? std::make_optional(BValue(old_to_new[*s->predicate()], &pb)) : std::nullopt, - n->loc()); + s->state_element()->non_synthesizable(), n->loc()); old_to_new[n] = copied_state.node(); if (send_state_values) { diff --git a/xls/dslx/ir_convert/function_converter.cc b/xls/dslx/ir_convert/function_converter.cc index ed71c27a42..5ca05dfd76 100644 --- a/xls/dslx/ir_convert/function_converter.cc +++ b/xls/dslx/ir_convert/function_converter.cc @@ -4306,8 +4306,10 @@ absl::Status FunctionConverter::HandleProcNextFunction( state_name = absl::StrCat("__", p->identifier()); Value init = f->params().size() > 1 ? initial_element.elements()[i] : initial_element; - XLS_ASSIGN_OR_RETURN(xls::StateElement * unread_state_element, - builder_ptr->UnreadStateElement(state_name, init)); + XLS_ASSIGN_OR_RETURN( + xls::StateElement * unread_state_element, + builder_ptr->UnreadStateElement(state_name, init, + /*non_synthesizable=*/false)); state_name_proto->set_name(state_name); XLS_ASSIGN_OR_RETURN(auto type, ResolveTypeToIr(p->type_annotation())); *state_name_proto->mutable_type() = type->ToProto(); diff --git a/xls/ir/clone_package_test.cc b/xls/ir/clone_package_test.cc index 74f6816a5d..2ac7d07f1f 100644 --- a/xls/ir/clone_package_test.cc +++ b/xls/ir/clone_package_test.cc @@ -117,5 +117,23 @@ TEST_F(ClonePackageTest, BasicBlock) { absl_testing::IsOkAndHolds(m::OutputPort(m::InstantiationOutput("foo")))); } +TEST_F(ClonePackageTest, CloneProcWithNonSynthesizableState) { + auto p = CreatePackage(); + ProcBuilder pb("prc", p.get()); + auto st_synth = pb.StateElement("synth", UBits(32, 32)); + auto st_non_synth = + pb.StateElement("non_synth", UBits(32, 32), /*non_synthesizable=*/true); + pb.Next(st_synth, st_synth); + pb.Next(st_non_synth, st_non_synth); + XLS_ASSERT_OK(pb.Build()); + + XLS_ASSERT_OK_AND_ASSIGN(auto p2, ClonePackage(p.get(), "foobar")); + XLS_ASSERT_OK_AND_ASSIGN(Proc * cp, p2->GetProc("prc")); + + ASSERT_EQ(cp->GetStateElementCount(), 2); + EXPECT_FALSE(cp->GetStateElement(0)->non_synthesizable()); + EXPECT_TRUE(cp->GetStateElement(1)->non_synthesizable()); +} + } // namespace } // namespace xls diff --git a/xls/ir/function_builder.cc b/xls/ir/function_builder.cc index cbcbdbfe12..6bbabd7f04 100644 --- a/xls/ir/function_builder.cc +++ b/xls/ir/function_builder.cc @@ -1507,12 +1507,13 @@ absl::StatusOr ProcBuilder::Build(absl::Span next_state) { BValue ProcBuilder::StateElement(std::string_view name, const Value& initial_value, std::optional read_predicate, + bool non_synthesizable, const SourceInfo& loc) { absl::StatusOr state_read = proc()->AppendStateElement( name, initial_value, read_predicate.has_value() ? std::make_optional(read_predicate->node()) : std::nullopt, - /*next_state=*/std::nullopt, loc); + /*next_state=*/std::nullopt, non_synthesizable, loc); if (!state_read.ok()) { return SetError(absl::StrFormat("Unable to add state element: %s", state_read.status().message()), @@ -1525,10 +1526,11 @@ BValue ProcBuilder::StateElement(std::string_view name, BValue ProcBuilder::StateElement(std::string_view name, const ValueBuilder& initial_value, std::optional read_predicate, + bool non_synthesizable, const SourceInfo& loc) { absl::StatusOr built = initial_value.Build(); if (built.ok()) { - return StateElement(name, *built, read_predicate, loc); + return StateElement(name, *built, read_predicate, non_synthesizable, loc); } return SetError(absl::StrFormat("Unable to create initial value due to %s", built.status().ToString()), @@ -1536,11 +1538,13 @@ BValue ProcBuilder::StateElement(std::string_view name, } absl::StatusOr ProcBuilder::UnreadStateElement( - std::string_view name, const Value& initial_value, const SourceInfo& loc) { + std::string_view name, const Value& initial_value, bool non_synthesizable, + const SourceInfo& loc) { if (ErrorPending()) { return GetError(); } - return proc()->AppendUnreadStateElement(name, initial_value, loc); + return proc()->AppendUnreadStateElement(name, initial_value, + non_synthesizable, loc); } BValue ProcBuilder::StateRead(class StateElement* state_element, diff --git a/xls/ir/function_builder.h b/xls/ir/function_builder.h index ecce51f364..546474a37a 100644 --- a/xls/ir/function_builder.h +++ b/xls/ir/function_builder.h @@ -893,34 +893,43 @@ class ProcBuilder : public BuilderBase { // predicate if provided). Returns the newly added state read. BValue StateElement(std::string_view name, const Value& initial_value, std::optional read_predicate, + bool non_synthesizable, const SourceInfo& loc = SourceInfo()); BValue StateElement(std::string_view name, const ValueBuilder& initial_value, std::optional read_predicate, + bool non_synthesizable, const SourceInfo& loc = SourceInfo()); BValue StateElement(std::string_view name, const Bits& initial_value, std::optional read_predicate, + bool non_synthesizable, const SourceInfo& loc = SourceInfo()) { - return StateElement(name, Value(initial_value), read_predicate, loc); + return StateElement(name, Value(initial_value), read_predicate, + non_synthesizable, loc); } BValue StateElement(std::string_view name, const Value& initial_value, + bool non_synthesizable = false, const SourceInfo& loc = SourceInfo()) { - return StateElement(name, initial_value, /*read_predicate=*/std::nullopt, + return StateElement(name, initial_value, + /*read_predicate=*/std::nullopt, non_synthesizable, loc); } BValue StateElement(std::string_view name, const ValueBuilder& initial_value, + bool non_synthesizable = false, const SourceInfo& loc = SourceInfo()) { return StateElement(name, initial_value, /*read_predicate=*/std::nullopt, - loc); + non_synthesizable, loc); } BValue StateElement(std::string_view name, const Bits& initial_value, + bool non_synthesizable = false, const SourceInfo& loc = SourceInfo()) { return StateElement(name, Value(initial_value), - /*read_predicate=*/std::nullopt, loc); + /*read_predicate=*/std::nullopt, non_synthesizable, + loc); } // Adds a state element to the proc without creating a state read. absl::StatusOr UnreadStateElement( - std::string_view name, const Value& initial_value, + std::string_view name, const Value& initial_value, bool non_synthesizable, const SourceInfo& loc = SourceInfo()); // Adds a state read node for an existing state element. diff --git a/xls/ir/function_builder_test.cc b/xls/ir/function_builder_test.cc index 86d267a27b..f8aba808c3 100644 --- a/xls/ir/function_builder_test.cc +++ b/xls/ir/function_builder_test.cc @@ -510,7 +510,8 @@ TEST(FunctionBuilderTest, UnreadStateElementAndStateRead) { XLS_ASSERT_OK_AND_ASSIGN( StateElement * state_element, - b.UnreadStateElement("my_state", Value(UBits(42, 32)))); + b.UnreadStateElement("my_state", Value(UBits(42, 32)), + /*non_synthesizable=*/false)); BValue cond = b.Literal(UBits(1, 1)); BValue not_cond = b.Not(cond); @@ -991,11 +992,14 @@ TEST(FunctionBuilderTest, StateReadIsDefinitelyEqualTo) { ProcBuilder pb("the_proc", &p); BValue pred = pb.Literal(UBits(1, 1)); Value v = Value(UBits(0, 32)); - BValue y_pred_label0 = pb.StateElement("y_pred_label0", v, pred); - BValue y_pred_label1 = pb.StateElement("y_pred_label1", v, pred); + BValue y_pred_label0 = pb.StateElement("y_pred_label0", v, pred, + /*non_synthesizable=*/false); + BValue y_pred_label1 = pb.StateElement("y_pred_label1", v, pred, + /*non_synthesizable=*/false); BValue y_pred_nolabel = pb.StateElement("y_nolabel_nopred", v); BValue y_nopred_label0 = pb.StateElement("y_nopred_label0", v); - BValue y_pred_label0_copy = pb.StateElement("y_nopred_copy", v, pred); + BValue y_pred_label0_copy = pb.StateElement("y_nopred_copy", v, pred, + /*non_synthesizable=*/false); y_pred_label0.node()->As()->set_label("label0"); y_pred_label1.node()->As()->set_label("label1"); diff --git a/xls/ir/ir_parser.cc b/xls/ir/ir_parser.cc index 46be4098ea..fce222be0e 100644 --- a/xls/ir/ir_parser.cc +++ b/xls/ir/ir_parser.cc @@ -2246,16 +2246,12 @@ absl::StatusOr> Parser::ParseProcSignature( /*should_verify=*/false); } for (int64_t i = 0; i < state_params.size(); ++i) { - BValue param_bvalue = - builder->StateElement(state_params[i].name, init_values[i]); + bool non_synthesizable = + non_synthesizable_states.contains(state_params[i].name); + BValue param_bvalue = builder->StateElement( + state_params[i].name, init_values[i], non_synthesizable); (*name_to_value)[state_params[i].name] = param_bvalue; param_bvalue.node()->SetId(state_params[i].id.value_or(kUnassignedNodeId)); - if (non_synthesizable_states.contains(state_params[i].name)) { - param_bvalue.node() - ->As() - ->state_element() - ->SetNonSynthesizable(); - } } return std::move(builder); diff --git a/xls/ir/proc.cc b/xls/ir/proc.cc index 4d88219dd8..fd4ee6beb6 100644 --- a/xls/ir/proc.cc +++ b/xls/ir/proc.cc @@ -255,18 +255,20 @@ absl::Status Proc::RemoveAllStateElements() { absl::StatusOr Proc::AppendStateElement( std::string_view requested_state_name, const Value& init_value, std::optional read_predicate, std::optional next_state, - const SourceInfo& loc) { + bool non_synthesizable, const SourceInfo& loc) { return InsertStateElement(GetStateElementCount(), requested_state_name, - init_value, read_predicate, next_state, loc); + init_value, read_predicate, next_state, + non_synthesizable, loc); } absl::StatusOr Proc::InsertUnreadStateElement( int64_t index, std::string_view requested_state_name, - const Value& init_value) { + const Value& init_value, bool non_synthesizable) { XLS_RET_CHECK_LE(index, GetStateElementCount()); std::string state_name = UniquifyStateName(requested_state_name); state_elements_[state_name] = std::make_unique( - state_name, package()->GetTypeForValue(init_value), init_value); + state_name, package()->GetTypeForValue(init_value), init_value, + non_synthesizable); StateElement* state_element = state_elements_.at(state_name).get(); state_vec_.insert(state_vec_.begin() + index, state_element); return state_element; @@ -287,10 +289,11 @@ absl::StatusOr Proc::AddStateRead(StateElement* state_element, absl::StatusOr Proc::InsertStateElement( int64_t index, std::string_view requested_state_name, const Value& init_value, std::optional read_predicate, - std::optional next_state, const SourceInfo& loc) { - XLS_ASSIGN_OR_RETURN( - StateElement * state_element, - InsertUnreadStateElement(index, requested_state_name, init_value)); + std::optional next_state, bool non_synthesizable, + const SourceInfo& loc) { + XLS_ASSIGN_OR_RETURN(StateElement * state_element, + InsertUnreadStateElement(index, requested_state_name, + init_value, non_synthesizable)); XLS_ASSIGN_OR_RETURN(StateRead * state_read, MakeNodeWithName( loc, state_element, read_predicate, @@ -373,7 +376,8 @@ absl::StatusOr Proc::Clone( ->InsertUnreadStateElement( cloned_proc->GetStateElementCount(), remap_name(state_name_remapping, state_element->name()), - state_element->initial_value()) + state_element->initial_value(), + state_element->non_synthesizable()) .status()); } if (is_new_style_proc()) { @@ -949,12 +953,10 @@ absl::StatusOr Proc::TransformStateElement( StateRead * new_state_read, AppendStateElement(absl::StrFormat("TEMP_NAME__%s__", orig_name), init_value, read_predicate, - /*next_state=*/std::nullopt)); + /*next_state=*/std::nullopt, + old_state_element->non_synthesizable())); new_state_read->SetLoc(old_state_read->loc()); new_state_read->set_label(old_state_read->label()); - if (old_state_read->state_element()->non_synthesizable()) { - new_state_read->state_element()->SetNonSynthesizable(); - } StateElement* new_state_element = new_state_read->state_element(); std::string temp_name = new_state_element->name(); diff --git a/xls/ir/proc.h b/xls/ir/proc.h index d6dd5d9b55..f55cb8c587 100644 --- a/xls/ir/proc.h +++ b/xls/ir/proc.h @@ -16,7 +16,6 @@ #define XLS_IR_PROC_H_ #include -#include #include #include #include @@ -223,13 +222,14 @@ class Proc : public FunctionBase { absl::StatusOr AppendStateElement( std::string_view requested_state_name, const Value& init_value, std::optional read_predicate, std::optional next_state, - const SourceInfo& loc = SourceInfo()); + bool non_synthesizable, const SourceInfo& loc = SourceInfo()); absl::StatusOr AppendStateElement( std::string_view requested_state_name, const Value& init_value, const SourceInfo& loc = SourceInfo()) { return AppendStateElement(requested_state_name, init_value, /*read_predicate=*/std::nullopt, - /*next_state=*/std::nullopt, loc); + /*next_state=*/std::nullopt, + /*non_synthesizable=*/false, loc); } // Adds a state read node for an existing state element. @@ -243,12 +243,13 @@ class Proc : public FunctionBase { // be added separately before verification. absl::StatusOr InsertUnreadStateElement( int64_t index, std::string_view requested_state_name, - const Value& init_value); + const Value& init_value, bool non_synthesizable); absl::StatusOr AppendUnreadStateElement( std::string_view requested_state_name, const Value& init_value, - const SourceInfo& loc = SourceInfo()) { + bool non_synthesizable, const SourceInfo& loc = SourceInfo()) { return InsertUnreadStateElement(GetStateElementCount(), - requested_state_name, init_value); + requested_state_name, init_value, + non_synthesizable); } // Adds a state element at the given index. Current state elements at the @@ -257,13 +258,15 @@ class Proc : public FunctionBase { absl::StatusOr InsertStateElement( int64_t index, std::string_view requested_state_name, const Value& init_value, std::optional read_predicate, - std::optional next_state, const SourceInfo& loc = SourceInfo()); + std::optional next_state, bool non_synthesizable, + const SourceInfo& loc = SourceInfo()); absl::StatusOr InsertStateElement( int64_t index, std::string_view requested_state_name, const Value& init_value, const SourceInfo& loc = SourceInfo()) { return InsertStateElement(index, requested_state_name, init_value, /*read_predicate=*/std::nullopt, - /*next_state=*/std::nullopt, loc); + /*next_state=*/std::nullopt, + /*non_synthesizable=*/false, loc); } bool HasImplicitUse(Node* node) const override; diff --git a/xls/ir/proc_test.cc b/xls/ir/proc_test.cc index 16b68917f4..f55514e68b 100644 --- a/xls/ir/proc_test.cc +++ b/xls/ir/proc_test.cc @@ -119,7 +119,8 @@ TEST_F(ProcTest, AddAndRemoveState) { XLS_ASSERT_OK(proc->AppendStateElement("y", Value(UBits(100, 32)), /*read_predicate=*/std::nullopt, - /*next_state=*/std::nullopt)); + /*next_state=*/std::nullopt, + /*non_synthesizable=*/false)); EXPECT_EQ(proc->GetStateElementCount(), 3); EXPECT_EQ(proc->GetStateElement(0)->name(), "tkn"); EXPECT_EQ(proc->GetStateElement(1)->name(), "x"); @@ -134,7 +135,8 @@ TEST_F(ProcTest, AddAndRemoveState) { SourceInfo(), Value(UBits(0, 32)), "zero")); XLS_ASSERT_OK(proc->AppendStateElement("z", Value(UBits(123, 32)), /*read_predicate=*/std::nullopt, - /*next_state=*/zero_literal)); + /*next_state=*/zero_literal, + /*non_synthesizable=*/false)); EXPECT_EQ(proc->GetStateElementCount(), 4); EXPECT_EQ(proc->GetStateElement(0)->name(), "tkn"); EXPECT_EQ(proc->GetStateElement(1)->name(), "x"); @@ -161,7 +163,8 @@ TEST_F(ProcTest, AddAndRemoveState) { XLS_ASSERT_OK(proc->InsertStateElement(0, "foo", Value(UBits(123, 32)), /*read_predicate=*/std::nullopt, - /*next_state=*/std::nullopt)); + /*next_state=*/std::nullopt, + /*non_synthesizable=*/false)); EXPECT_EQ(proc->GetStateElementCount(), 4); EXPECT_EQ(proc->GetStateElement(0)->name(), "foo"); EXPECT_EQ(proc->GetStateElement(1)->name(), "tkn"); @@ -170,7 +173,8 @@ TEST_F(ProcTest, AddAndRemoveState) { XLS_ASSERT_OK(proc->InsertStateElement(4, "bar", Value(UBits(1, 64)), /*read_predicate=*/std::nullopt, - /*next_state=*/std::nullopt)); + /*next_state=*/std::nullopt, + /*non_synthesizable=*/false)); EXPECT_EQ(proc->GetStateElementCount(), 5); EXPECT_EQ(proc->GetStateElement(0)->name(), "foo"); EXPECT_EQ(proc->GetStateElement(1)->name(), "tkn"); diff --git a/xls/ir/state_element.h b/xls/ir/state_element.h index fe4c967cef..70da358fca 100644 --- a/xls/ir/state_element.h +++ b/xls/ir/state_element.h @@ -46,7 +46,6 @@ class StateElement { void SetName(std::string_view name) { name_ = name; } void SetName(std::string&& name) { name_ = std::move(name); } - void SetNonSynthesizable() { non_synthesizable_ = true; } std::string ToString() const; diff --git a/xls/passes/array_untuple_pass.cc b/xls/passes/array_untuple_pass.cc index 7dd041342c..80daaa685a 100644 --- a/xls/passes/array_untuple_pass.cc +++ b/xls/passes/array_untuple_pass.cc @@ -319,7 +319,8 @@ class UntupleVisitor : public DfsVisitorWithDefault { *std::back_inserter(res), proc->AppendStateElement( absl::StrFormat("%s_tuple_element_%d", state_element->name(), i), - std::move(element_array))); + std::move(element_array), /*read_predicate=*/std::nullopt, + /*next_state=*/std::nullopt, state_element->non_synthesizable())); } return RecordUntuple(state_read, std::move(res)); } diff --git a/xls/passes/array_untuple_pass_test.cc b/xls/passes/array_untuple_pass_test.cc index 26fbda8db8..e27d01f18e 100644 --- a/xls/passes/array_untuple_pass_test.cc +++ b/xls/passes/array_untuple_pass_test.cc @@ -536,8 +536,9 @@ TEST_F(ArrayUntuplePassTest, ProcStateArrayNextWithStateElement) { ValueBuilder::Tuple({Value(UBits(0, 4)), Value(UBits(0, 8))})}) .Build()); - XLS_ASSERT_OK_AND_ASSIGN(StateElement * state_elem, - pb.UnreadStateElement("my_state", init_val)); + XLS_ASSERT_OK_AND_ASSIGN( + StateElement * state_elem, + pb.UnreadStateElement("my_state", init_val, /*non_synthesizable=*/false)); BValue state_read = pb.StateRead(state_elem); BValue updated = pb.ArrayUpdate( diff --git a/xls/passes/canonicalization_pass_test.cc b/xls/passes/canonicalization_pass_test.cc index bc6ce425eb..27fb038447 100644 --- a/xls/passes/canonicalization_pass_test.cc +++ b/xls/passes/canonicalization_pass_test.cc @@ -345,7 +345,8 @@ TEST_F(CanonicalizePassTest, StateReadWithAlwaysTruePredicate) { auto p = CreatePackage(); ProcBuilder pb("test", p.get()); BValue x = pb.StateElement("x", Value(UBits(0, 32)), - /*read_predicate=*/pb.Literal(UBits(1, 1))); + /*read_predicate=*/pb.Literal(UBits(1, 1)), + /*non_synthesizable=*/false); pb.Next(x, pb.Literal(UBits(1, 32))); XLS_ASSERT_OK_AND_ASSIGN(Proc * proc, pb.Build()); EXPECT_THAT(proc->GetStateRead(0)->predicate(), Optional(m::Literal(1))); diff --git a/xls/passes/non_synth_separation_pass.cc b/xls/passes/non_synth_separation_pass.cc index 9d3af75ad4..cc2a449986 100644 --- a/xls/passes/non_synth_separation_pass.cc +++ b/xls/passes/non_synth_separation_pass.cc @@ -314,8 +314,8 @@ class CloneProcAsFunctionVisitor : public DfsVisitorWithDefault { std::string name = absl::StrCat(state_element->name(), "_non_synth"); XLS_ASSIGN_OR_RETURN( StateElement * new_element, - proc->AppendUnreadStateElement(name, state_element->initial_value())); - new_element->SetNonSynthesizable(); + proc->AppendUnreadStateElement(name, state_element->initial_value(), + /*non_synthesizable=*/true)); non_synth_element_map_[state_element] = new_element; return new_element; } diff --git a/xls/passes/proc_state_array_flattening_pass_test.cc b/xls/passes/proc_state_array_flattening_pass_test.cc index 4a2075eb34..41754be6d9 100644 --- a/xls/passes/proc_state_array_flattening_pass_test.cc +++ b/xls/passes/proc_state_array_flattening_pass_test.cc @@ -133,7 +133,8 @@ TEST_F(ProcStateArrayFlatteningPassTest, StateElement * state, pb.UnreadStateElement( "state", - Value::ArrayOrDie({Value(UBits(10, 32)), Value(UBits(20, 32))}))); + Value::ArrayOrDie({Value(UBits(10, 32)), Value(UBits(20, 32))}), + /*non_synthesizable=*/false)); BValue read = pb.StateRead(state, /*predicate=*/std::nullopt, /*label=*/"my_read_label"); diff --git a/xls/passes/proc_state_optimization_pass.cc b/xls/passes/proc_state_optimization_pass.cc index 403ec618ad..a8ec89081a 100644 --- a/xls/passes/proc_state_optimization_pass.cc +++ b/xls/passes/proc_state_optimization_pass.cc @@ -376,16 +376,22 @@ absl::Status ConstantChainToStateMachine(Proc* proc, CHECK(!chain.empty()); std::string state_machine_name = "state_machine"; + bool non_synthesizable = false; for (int64_t state_index : chain) { absl::StrAppend(&state_machine_name, "_", proc->GetStateElement(state_index)->name()); + if (proc->GetStateElement(state_index)->non_synthesizable()) { + non_synthesizable = true; + } } int64_t state_machine_width = CeilOfLog2(chain.size()) + 1; Type* state_machine_type = proc->package()->GetBitsType(state_machine_width); XLS_ASSIGN_OR_RETURN(StateRead * state_machine_read, proc->AppendStateElement( - state_machine_name, ZeroOfType(state_machine_type))); + state_machine_name, ZeroOfType(state_machine_type), + /*read_predicate=*/std::nullopt, + /*next_state=*/std::nullopt, non_synthesizable)); { XLS_ASSIGN_OR_RETURN( diff --git a/xls/passes/proc_state_tuple_flattening_pass.cc b/xls/passes/proc_state_tuple_flattening_pass.cc index db529c032e..5283361884 100644 --- a/xls/passes/proc_state_tuple_flattening_pass.cc +++ b/xls/passes/proc_state_tuple_flattening_pass.cc @@ -167,16 +167,13 @@ absl::Status ReplaceProcState(Proc* proc, for (const AbstractStateElement& element : elements) { XLS_ASSIGN_OR_RETURN( StateRead * read, - proc->AppendStateElement(element.name, element.initial_value, - element.read_predicate, - /*next_state=*/std::nullopt)); + proc->AppendStateElement( + element.name, element.initial_value, element.read_predicate, + /*next_state=*/std::nullopt, element.non_synthesizable)); read->SetLoc(element.placeholder->loc()); if (element.read_label.has_value()) { read->set_label(element.read_label); } - if (element.non_synthesizable) { - read->state_element()->SetNonSynthesizable(); - } for (const NextValue& next_value : element.next_values) { XLS_RETURN_IF_ERROR(proc->MakeNodeWithName( next_value.loc, diff --git a/xls/passes/proc_state_tuple_flattening_pass_test.cc b/xls/passes/proc_state_tuple_flattening_pass_test.cc index ba7295e936..cb6b7e1bcb 100644 --- a/xls/passes/proc_state_tuple_flattening_pass_test.cc +++ b/xls/passes/proc_state_tuple_flattening_pass_test.cc @@ -423,7 +423,8 @@ TEST_F(ProcStateFlatteningPassTest, XLS_ASSERT_OK_AND_ASSIGN( StateElement * state, pb.UnreadStateElement( - "state", Value::Tuple({Value(UBits(10, 32)), Value(UBits(20, 32))}))); + "state", Value::Tuple({Value(UBits(10, 32)), Value(UBits(20, 32))}), + /*non_synthesizable=*/false)); BValue read = pb.StateRead(state, /*predicate=*/std::nullopt, /*label=*/"my_read_label"); diff --git a/xls/passes/select_simplification_pass_test.cc b/xls/passes/select_simplification_pass_test.cc index b62f090fa3..43f6ca3f8d 100644 --- a/xls/passes/select_simplification_pass_test.cc +++ b/xls/passes/select_simplification_pass_test.cc @@ -1834,9 +1834,11 @@ TEST_P(SelectSimplificationPassTest, PredicatedStateReadFeedSelector) { auto p = CreatePackage(); TokenlessProcBuilder pb(NewStyleProc{}, TestName(), "tkn", p.get()); XLS_ASSERT_OK_AND_ASSIGN(StateElement * state_element1, - pb.UnreadStateElement("state1", Value(UBits(0, 1)))); + pb.UnreadStateElement("state1", Value(UBits(0, 1)), + /*non_synthesizable=*/false)); XLS_ASSERT_OK_AND_ASSIGN(StateElement * state_element2, - pb.UnreadStateElement("state2", Value(UBits(0, 1)))); + pb.UnreadStateElement("state2", Value(UBits(0, 1)), + /*non_synthesizable=*/false)); XLS_ASSERT_OK_AND_ASSIGN(auto in1, pb.AddInputChannel("in1", p->GetBitsType(32))); XLS_ASSERT_OK_AND_ASSIGN(auto in2, diff --git a/xls/scheduling/pipeline_schedule_test.cc b/xls/scheduling/pipeline_schedule_test.cc index 49cd0211eb..350c9b8f04 100644 --- a/xls/scheduling/pipeline_schedule_test.cc +++ b/xls/scheduling/pipeline_schedule_test.cc @@ -194,7 +194,8 @@ absl::StatusOr BuildLabeledFeedbackArcProc( ProcBuilder pb("the_proc", package.get()); BValue tkn = pb.Literal(Value::Token()); XLS_ASSIGN_OR_RETURN(auto se, - pb.UnreadStateElement("state", Value(UBits(0, 32)))); + pb.UnreadStateElement("state", Value(UBits(0, 32)), + /*non_synthesizable=*/false)); BValue read = pb.StateRead(se, /*predicate=*/std::nullopt, read_label); BValue add_val = pb.Add(read, pb.Literal(UBits(1, 32))); pb.Send(out_ch, tkn, add_val); @@ -2316,7 +2317,8 @@ TEST_P(PipelineScheduleTest, ProcWithExplicitStateAccess) { TokenlessProcBuilder pb("the_proc", "tkn", &p); XLS_ASSERT_OK_AND_ASSIGN(StateElement * se, - pb.UnreadStateElement("state", Value(UBits(0, 32)))); + pb.UnreadStateElement("state", Value(UBits(0, 32)), + /*non_synthesizable=*/false)); BValue current = pb.StateRead(se); BValue add_val = pb.Add(current, pb.Literal(UBits(1, 32))); @@ -2345,7 +2347,8 @@ TEST_P(PipelineScheduleTest, ProcWithMultipleStateReads) { TokenlessProcBuilder pb("the_proc", "tkn", &p); XLS_ASSERT_OK_AND_ASSIGN(StateElement * se, - pb.UnreadStateElement("state", Value(UBits(0, 32)))); + pb.UnreadStateElement("state", Value(UBits(0, 32)), + /*non_synthesizable=*/false)); BValue read1 = pb.StateRead(se); // Create a second read with a predicate @@ -2373,7 +2376,8 @@ TEST_P(PipelineScheduleErrorTest, ProcWithZeroReadsErrors) { Package p(TestName()); TokenlessProcBuilder pb("the_proc", "tkn", &p); XLS_ASSERT_OK_AND_ASSIGN(StateElement * se, - pb.UnreadStateElement("state", Value(UBits(0, 32)))); + pb.UnreadStateElement("state", Value(UBits(0, 32)), + /*non_synthesizable=*/false)); BValue add_val = pb.Literal(UBits(42, 32)); pb.Next(se, add_val); @@ -2658,7 +2662,8 @@ TEST_F(PipelineScheduleTest, ProcFeedbackArcThroughputMultiProc) { // Proc 1: has ("W1", "R1") ProcBuilder pb1("proc_1", package.get()); XLS_ASSERT_OK_AND_ASSIGN(auto se1, - pb1.UnreadStateElement("st1", Value(UBits(0, 32)))); + pb1.UnreadStateElement("st1", Value(UBits(0, 32)), + /*non_synthesizable=*/false)); BValue read1 = pb1.StateRead(se1, /*predicate=*/std::nullopt, "R1"); BValue add1 = pb1.Add(read1, pb1.Literal(UBits(1, 32))); pb1.Next(se1, add1, /*pred=*/std::nullopt, "W1"); @@ -2667,7 +2672,8 @@ TEST_F(PipelineScheduleTest, ProcFeedbackArcThroughputMultiProc) { // Proc 2: has ("W2", "R2") ProcBuilder pb2("proc_2", package.get()); XLS_ASSERT_OK_AND_ASSIGN(auto se2, - pb2.UnreadStateElement("st2", Value(UBits(0, 32)))); + pb2.UnreadStateElement("st2", Value(UBits(0, 32)), + /*non_synthesizable=*/false)); BValue read2 = pb2.StateRead(se2, /*predicate=*/std::nullopt, "R2"); BValue add2 = pb2.Add(read2, pb2.Literal(UBits(1, 32))); pb2.Next(se2, add2, /*pred=*/std::nullopt, "W2"); @@ -2727,7 +2733,8 @@ TEST_F(PipelineScheduleTest, ProcStateReadBeforeWriteSucceeds) { ProcBuilder pb("the_proc", &p); BValue tkn = pb.Literal(Value::Token()); XLS_ASSERT_OK_AND_ASSIGN(StateElement * se, - pb.UnreadStateElement("state", Value(UBits(0, 32)))); + pb.UnreadStateElement("state", Value(UBits(0, 32)), + /*non_synthesizable=*/false)); // Read state value, add logic to force it late in the pipeline BValue read = pb.StateRead(se); @@ -2771,7 +2778,8 @@ TEST_F(PipelineScheduleTest, ProcBuilder pb("the_proc", &p); BValue tkn = pb.Literal(Value::Token()); XLS_ASSERT_OK_AND_ASSIGN(StateElement * se, - pb.UnreadStateElement("state", Value(UBits(0, 32)))); + pb.UnreadStateElement("state", Value(UBits(0, 32)), + /*non_synthesizable=*/false)); BValue rcv = pb.Receive(in_ch, tkn); BValue rcv_tkn = pb.TupleIndex(rcv, 0); BValue cond = pb.TupleIndex(rcv, 1); @@ -2813,7 +2821,8 @@ TEST_F(PipelineScheduleTest, ProcWriteBeforeReadFailsVerification) { Package p(TestName()); ProcBuilder pb("the_proc", &p); XLS_ASSERT_OK_AND_ASSIGN(StateElement * se, - pb.UnreadStateElement("state", Value(UBits(0, 32)))); + pb.UnreadStateElement("state", Value(UBits(0, 32)), + /*non_synthesizable=*/false)); BValue read = pb.StateRead(se); BValue next = pb.Next(se, pb.Literal(UBits(42, 32))); XLS_ASSERT_OK_AND_ASSIGN(Proc * proc, pb.Build()); @@ -2844,7 +2853,8 @@ TEST_F(PipelineScheduleTest, ProcFeedbackArcTooLongFailsVerification) { Package p(TestName()); ProcBuilder pb("the_proc", &p); XLS_ASSERT_OK_AND_ASSIGN(StateElement * se, - pb.UnreadStateElement("state", Value(UBits(0, 32)))); + pb.UnreadStateElement("state", Value(UBits(0, 32)), + /*non_synthesizable=*/false)); pb.StateRead(se); BValue next = pb.Next(se, pb.Literal(UBits(42, 32))); XLS_ASSERT_OK_AND_ASSIGN(Proc * proc, pb.Build()); diff --git a/xls/scheduling/proc_state_legalization_pass_test.cc b/xls/scheduling/proc_state_legalization_pass_test.cc index 668a585827..2bab5504a8 100644 --- a/xls/scheduling/proc_state_legalization_pass_test.cc +++ b/xls/scheduling/proc_state_legalization_pass_test.cc @@ -375,7 +375,8 @@ TEST_P(ProcStateLegalizationPassTest, ProcWithPredicatedStateRead) { BValue x_multiple_of_3 = pb.Eq(pb.UMod(x, pb.Literal(UBits(3, 32))), pb.Literal(UBits(0, 32))); BValue y = pb.StateElement("y", Value(UBits(0, 32)), - /*read_predicate=*/x_even); + /*read_predicate=*/x_even, + /*non_synthesizable=*/false); pb.Next(x, pb.Add(x, pb.Literal(UBits(1, 32)))); pb.Next(y, pb.Add(y, pb.Literal(UBits(1, 32))), x_multiple_of_3); XLS_ASSERT_OK_AND_ASSIGN(Proc * proc, pb.Build()); @@ -431,7 +432,8 @@ TEST_P(ProcStateLegalizationPassTest, BValue x_multiple_of_3 = pb.Eq(pb.UMod(x, pb.Literal(UBits(3, 32))), pb.Literal(UBits(0, 32))); BValue y = pb.StateElement("y", Value(UBits(0, 32)), - /*read_predicate=*/x_even); + /*read_predicate=*/x_even, + /*non_synthesizable=*/false); BValue y_even = pb.Eq(pb.UMod(y, pb.Literal(UBits(2, 32))), pb.Literal(UBits(0, 32))); pb.Next(x, pb.Add(x, pb.Literal(UBits(1, 32)))); @@ -503,7 +505,8 @@ TEST_P(ProcStateLegalizationPassTest, BValue x_not_multiple_of_3 = pb.Not(x_multiple_of_3); BValue disjunction = pb.Or(x_multiple_of_3, x_not_multiple_of_3); BValue y = pb.StateElement("y", Value(UBits(0, 32)), - /*read_predicate=*/disjunction); + /*read_predicate=*/disjunction, + /*non_synthesizable=*/false); pb.Next(x, pb.Add(x, pb.Literal(UBits(1, 32)))); pb.Next(y, pb.Add(y, pb.Literal(UBits(1, 32))), x_multiple_of_3); pb.Next(y, y, x_not_multiple_of_3); diff --git a/xls/scheduling/schedule_util_test.cc b/xls/scheduling/schedule_util_test.cc index fa52d3a959..1e879419ca 100644 --- a/xls/scheduling/schedule_util_test.cc +++ b/xls/scheduling/schedule_util_test.cc @@ -75,10 +75,12 @@ TEST_F(ScheduleUtilTest, GetDeadAfterSynthesisNodesState) { pb.AddInputChannel("foo", p->GetBitsType(32))); XLS_ASSERT_OK_AND_ASSIGN(auto chan_out, pb.AddOutputChannel("bar", p->GetBitsType(32))); - BValue state = pb.StateElement("state_real", UBits(1, 32), std::nullopt); + BValue state = pb.StateElement("state_real", UBits(1, 32), std::nullopt, + /*non_synthesizable=*/false); pb.Send(chan_out, state); BValue non_synth_state = - pb.StateElement("nonsynth", UBits(0, 32), std::nullopt); + pb.StateElement("nonsynth", UBits(0, 32), std::nullopt, + /*non_synthesizable=*/false); BValue cond = pb.UGe(state, non_synth_state); BValue assert = pb.Assert(pb.InitialToken(), cond, "assert"); BValue recv = pb.Receive(chan); @@ -103,10 +105,12 @@ TEST_F(ScheduleUtilTest, GetDeadAfterSynthesisStateChasing) { pb.AddInputChannel("foo", p->GetBitsType(32))); XLS_ASSERT_OK_AND_ASSIGN(auto chan_out, pb.AddOutputChannel("bar", p->GetBitsType(32))); - BValue state = pb.StateElement("state_real", UBits(1, 32), std::nullopt); + BValue state = pb.StateElement("state_real", UBits(1, 32), std::nullopt, + /*non_synthesizable=*/false); pb.Send(chan_out, state); // State is kept synth due to being the source of next cycles 'state_real'. - BValue synth_state = pb.StateElement("nonsynth", UBits(0, 32), std::nullopt); + BValue synth_state = pb.StateElement("nonsynth", UBits(0, 32), std::nullopt, + /*non_synthesizable=*/false); BValue cond = pb.UGe(state, synth_state); BValue assert = pb.Assert(pb.InitialToken(), cond, "assert"); BValue recv = pb.Receive(chan); @@ -239,8 +243,8 @@ TEST_F(ScheduleUtilTest, GetFeedbackArcsTest) { // Proc 1 ProcBuilder pb1(TestName(), p.get()); XLS_ASSERT_OK_AND_ASSIGN( - StateElement * se1, - pb1.UnreadStateElement("state1", Value(UBits(42, 32)))); + StateElement * se1, pb1.UnreadStateElement("state1", Value(UBits(42, 32)), + /*non_synthesizable=*/false)); BValue read1 = pb1.StateRead(se1, /*predicate=*/std::nullopt, "my_read1"); BValue add_val1 = pb1.Add(read1, pb1.Literal(UBits(1, 32))); pb1.Next(se1, add_val1, /*predicate=*/std::nullopt, "my_write1"); @@ -250,7 +254,8 @@ TEST_F(ScheduleUtilTest, GetFeedbackArcsTest) { ProcBuilder pb2("proc_2", p.get()); XLS_ASSERT_OK_AND_ASSIGN( StateElement * se2, - pb2.UnreadStateElement("state2", Value(UBits(100, 32)))); + pb2.UnreadStateElement("state2", Value(UBits(100, 32)), + /*non_synthesizable=*/false)); BValue read2 = pb2.StateRead(se2, /*predicate=*/std::nullopt, "my_read2"); BValue add_val2 = pb2.Add(read2, pb2.Literal(UBits(5, 32))); pb2.Next(se2, add_val2, /*predicate=*/std::nullopt, "my_write2");