diff --git a/xls/dslx/ir_convert/function_converter.cc b/xls/dslx/ir_convert/function_converter.cc index 7b675e484f..c0fed7ea48 100644 --- a/xls/dslx/ir_convert/function_converter.cc +++ b/xls/dslx/ir_convert/function_converter.cc @@ -2655,25 +2655,29 @@ absl::Status FunctionConverter::HandleCoverBuiltin(const Invocation* node, absl::Status FunctionConverter::HandleBuiltinRead(const Invocation* node) { XLS_RETURN_IF_ERROR(ValidateProcState("read", node)); XLS_RET_CHECK_EQ(node->args().size(), 1); + Expr* source = node->args()[0]; BValue active = implicit_token_data_->create_control_predicate(); - if (state_read_called_.has_value()) { + BValue state_read_called = state_read_map_[source->ToString()]; + if (options_.emit_assert) { // Assert multiple reads don't happen in same activation. implicit_token_data_->entry_token = function_builder_->Assert( implicit_token_data_->entry_token, function_builder_->Or(function_builder_->Not(active), - function_builder_->Not(*state_read_called_)), + function_builder_->Not(state_read_called)), "State element read after read in same activation."); - state_read_called_ = function_builder_->Or(*state_read_called_, active); implicit_token_data_->control_tokens.push_back( implicit_token_data_->entry_token); } - - Expr* source = node->args()[0]; + state_read_map_[source->ToString()] = + function_builder_->Or(state_read_called, active); XLS_RETURN_IF_ERROR(Visit(source)); - XLS_ASSIGN_OR_RETURN(BValue state_element, Use(source)); + XLS_ASSIGN_OR_RETURN(BValue state_read, Use(source)); + if (node->label().has_value()) { + state_read.node()->As()->set_label(*node->label()); + } Def(node, [&](const SourceInfo& loc) { - return function_builder_->Identity(state_element, loc); + return function_builder_->Identity(state_read, loc); }); return absl::OkStatus(); } @@ -2683,34 +2687,36 @@ absl::Status FunctionConverter::HandleBuiltinWrite(const Invocation* node) { XLS_RET_CHECK_EQ(node->args().size(), 2); XLS_RETURN_IF_ERROR(Visit(node->args()[1])); XLS_ASSIGN_OR_RETURN(BValue update_val, Use(node->args()[1])); + Expr* target = node->args()[0]; BValue active = implicit_token_data_->create_control_predicate(); - if (state_read_called_.has_value() && state_write_called_.has_value()) { + BValue state_read_called = state_read_map_[target->ToString()]; + BValue state_write_called = state_write_map_[target->ToString()]; + if (options_.emit_assert) { // Assert write doesn't happen before a read implicit_token_data_->entry_token = function_builder_->Assert( implicit_token_data_->entry_token, function_builder_->Or(function_builder_->Not(active), - *state_read_called_), + state_read_called), "State element written before read in same activation."); // Assert multiple writes don't happen in same activation implicit_token_data_->entry_token = function_builder_->Assert( implicit_token_data_->entry_token, function_builder_->Or(function_builder_->Not(active), - function_builder_->Not(*state_write_called_)), + function_builder_->Not(state_write_called)), "State element written after write in same activation."); - state_write_called_ = function_builder_->Or(*state_write_called_, active); implicit_token_data_->control_tokens.push_back( implicit_token_data_->entry_token); } - - Expr* target = node->args()[0]; + state_write_map_[target->ToString()] = + function_builder_->Or(state_write_called, active); XLS_RETURN_IF_ERROR(Visit(target)); - XLS_ASSIGN_OR_RETURN(BValue state_element, Use(target)); + XLS_ASSIGN_OR_RETURN(BValue state_read, Use(target)); ProcBuilder* builder_ptr = dynamic_cast(function_builder_.get()); - builder_ptr->Next(state_element, update_val, active); + builder_ptr->Next(state_read, update_val, active, node->label()); node_to_ir_[node] = function_builder_->Tuple({}); return absl::OkStatus(); } @@ -3722,8 +3728,10 @@ absl::Status FunctionConverter::HandleProcNextFunction( module_->attributes().contains(ModuleAttribute::kExplicitStateAccess); BValue state = builder->StateElement(state_name, initial_element); if (explicit_state_access) { - state_read_called_ = builder->Literal(UBits(0, 1)); - state_write_called_ = builder->Literal(UBits(0, 1)); + for (Param* p : f->params()) { + state_read_map_[p->identifier()] = builder->Literal(UBits(0, 1)); + state_write_map_[p->identifier()] = builder->Literal(UBits(0, 1)); + } } tokens_.push_back(implicit_token); auto* builder_ptr = builder.get(); @@ -3733,14 +3741,32 @@ absl::Status FunctionConverter::HandleProcNextFunction( XLS_RETURN_IF_ERROR(builder_ptr->SetAsTop()); } - // Set the one state element. + // Set the state element(s). XLS_RET_CHECK(proc_proto_); - PackageInterfaceProto::NamedValue* state_proto = - proc_proto_.value()->add_state(); - *state_proto->mutable_name() = state_name; - *state_proto->mutable_type() = state.GetType()->ToProto(); - // State elements aren't emitted in an observable way so no need to track sv - // types. + if (explicit_state_access) { + for (int i = 0; i < f->params().size(); ++i) { + Param* p = f->params()[i]; + PackageInterfaceProto::Proc::StateValue* state_value = + proc_proto_.value()->add_state_values(); + PackageInterfaceProto::NamedValue* state_proto = + state_value->mutable_name(); + state_proto->set_name(p->identifier()); + XLS_ASSIGN_OR_RETURN(auto type, ResolveTypeToIr(p->type_annotation())); + *state_proto->mutable_type() = type->ToProto(); + Value init = f->params().size() > 1 ? initial_element.elements()[i] + : initial_element; + BValue p_state = builder_ptr->StateElement(p->identifier(), init); + SetNodeToIr(p->name_def(), p_state); + } + } else { + PackageInterfaceProto::NamedValue* state_proto = + proc_proto_.value()->add_state(); + *state_proto->mutable_name() = state_name; + *state_proto->mutable_type() = state.GetType()->ToProto(); + // Bind the recurrent state element. + XLS_RET_CHECK_EQ(f->params().size(), 1); + SetNodeToIr(f->params()[0]->name_def(), state); + } // We make an implicit token in case any downstream functions need it; if it's // unused, it'll be optimized out later. @@ -3751,10 +3777,6 @@ absl::Status FunctionConverter::HandleProcNextFunction( [this]() { return implicit_token_data_->activated; }, }; - // Bind the recurrent state element. - XLS_RET_CHECK_EQ(f->params().size(), 1); - SetNodeToIr(f->params()[0]->name_def(), state); - proc_id_ = proc_id; for (ParametricBinding* parametric_binding : f->parametric_bindings()) { diff --git a/xls/dslx/ir_convert/function_converter.h b/xls/dslx/ir_convert/function_converter.h index 1d0df863fb..95d4828ede 100644 --- a/xls/dslx/ir_convert/function_converter.h +++ b/xls/dslx/ir_convert/function_converter.h @@ -495,6 +495,8 @@ class FunctionConverter { absl::Status HandleBuiltinEnumerate(const Invocation* node); absl::Status HandleBuiltinGate(const Invocation* node); absl::Status HandleBuiltinJoin(const Invocation* node); + absl::Status HandleBuiltinLabeledRead(const Invocation* node); + absl::Status HandleBuiltinLabeledWrite(const Invocation* node); absl::Status HandleBuiltinOneHot(const Invocation* node); absl::Status HandleBuiltinOneHotSel(const Invocation* node); absl::Status HandleBuiltinOrReduce(const Invocation* node); @@ -666,8 +668,8 @@ class FunctionConverter { // A predicate for whether any code path leading to a state read or write has // been taken each proc activation. This gets updated to accumulate terms // every time we emit a state read/write. - std::optional state_read_called_; - std::optional state_write_called_; + absl::flat_hash_map state_read_map_; + absl::flat_hash_map state_write_map_; }; } // namespace xls::dslx diff --git a/xls/dslx/ir_convert/ir_converter_test.cc b/xls/dslx/ir_convert/ir_converter_test.cc index 6b98bcfbb4..fe51b7a5e9 100644 --- a/xls/dslx/ir_convert/ir_converter_test.cc +++ b/xls/dslx/ir_convert/ir_converter_test.cc @@ -8342,7 +8342,7 @@ proc p { } TEST_F(IrConverterTest, ExplicitStateAccessMultipleReads) { - constexpr std::string_view program = R"(#![feature(explicit_state_access)] + constexpr std::string_view kModule = R"(#![feature(explicit_state_access)] proc main { config() { () } @@ -8356,12 +8356,12 @@ proc main { } )"; XLS_ASSERT_OK_AND_ASSIGN(std::string converted, - ConvertModuleForTest(program)); + ConvertModuleForTest(kModule)); ExpectIr(converted); } TEST_F(IrConverterTest, ExplicitStateAccessMultipleWrites) { - constexpr std::string_view program = R"(#![feature(explicit_state_access)] + constexpr std::string_view kModule = R"(#![feature(explicit_state_access)] proc main { config() { () } @@ -8376,12 +8376,12 @@ proc main { } )"; XLS_ASSERT_OK_AND_ASSIGN(std::string converted, - ConvertModuleForTest(program)); + ConvertModuleForTest(kModule)); ExpectIr(converted); } TEST_F(IrConverterTest, ExplicitStateAccessWriteBeforeRead) { - constexpr std::string_view program = R"(#![feature(explicit_state_access)] + constexpr std::string_view kModule = R"(#![feature(explicit_state_access)] proc main { config() { () } @@ -8393,12 +8393,12 @@ proc main { } )"; XLS_ASSERT_OK_AND_ASSIGN(std::string converted, - ConvertModuleForTest(program)); + ConvertModuleForTest(kModule)); ExpectIr(converted); } TEST_F(IrConverterTest, ExplicitStateAccessConditionalWrite) { - constexpr std::string_view program = R"(#![feature(explicit_state_access)] + constexpr std::string_view kModule = R"(#![feature(explicit_state_access)] proc main { config() { () } @@ -8415,12 +8415,12 @@ proc main { } )"; XLS_ASSERT_OK_AND_ASSIGN(std::string converted, - ConvertModuleForTest(program)); + ConvertModuleForTest(kModule)); ExpectIr(converted); } TEST_F(IrConverterTest, ExplicitStateAccessMatch) { - constexpr std::string_view program = R"(#![feature(explicit_state_access)] + constexpr std::string_view kModule = R"(#![feature(explicit_state_access)] proc main { config() { () } init { 0 } @@ -8442,12 +8442,12 @@ proc main { } )"; XLS_ASSERT_OK_AND_ASSIGN(std::string converted, - ConvertModuleForTest(program)); + ConvertModuleForTest(kModule)); ExpectIr(converted); } TEST_F(IrConverterTest, ExplicitStateAccessMatchMultipleWrites) { - constexpr std::string_view program = R"(#![feature(explicit_state_access)] + constexpr std::string_view kModule = R"(#![feature(explicit_state_access)] proc main { config() { () } init { true } @@ -8467,7 +8467,118 @@ proc main { } )"; XLS_ASSERT_OK_AND_ASSIGN(std::string converted, - ConvertModuleForTest(program)); + ConvertModuleForTest(kModule)); + ExpectIr(converted); +} + +TEST_F(IrConverterTest, ExplicitStateAccessLabeledReadAndWrite) { + constexpr std::string_view kModule = R"(#![feature(explicit_state_access)] +proc main { + init { 0 } + config() { } + next(state: u32) { + let x = 'main_read:read(state); + let y = x + 1; + 'main_write:write(state, y); + } +} +)"; + XLS_ASSERT_OK_AND_ASSIGN(std::string converted, + ConvertModuleForTest(kModule)); + ExpectIr(converted); +} + +TEST_F(IrConverterTest, ExplicitStateAccessReadWithLabeledRead) { + constexpr std::string_view kModule = R"(#![feature(explicit_state_access)] +proc main { + init { 0 } + config() { } + next(state: u32) { + let curr = read(state); + let x = 'main_read:read(state); + let y = x + 1 + curr; + 'main_write:write(state, y); + } +} +)"; + XLS_ASSERT_OK_AND_ASSIGN(std::string converted, + ConvertModuleForTest(kModule)); + ExpectIr(converted); +} + +TEST_F(IrConverterTest, ExplicitStateAccessMultipleStates) { + constexpr std::string_view kModule = R"(#![feature(explicit_state_access)] +struct Point { + x: u32, + y: u32, +} + proc main { + init { (Point { x: 0, y: 1 }, (2, 3), 4) } + config() { } + next(state_0: Point, state_1: (u32, u32), state_2: u32) { + let a = read(state_0); + let b = read(state_1); + let c = read(state_2); + let new_a = Point { x: a.x + 1, y: b.1 + c }; + let new_b = (b.0 + 1, c + 1); + write(state_0, new_a); + write(state_1, new_b); + write(state_2, c + 2); + } +} +)"; + XLS_ASSERT_OK_AND_ASSIGN(std::string converted, + ConvertModuleForTest(kModule)); + ExpectIr(converted); +} + +TEST_F(IrConverterTest, ExplicitStateAccessMultipleStatesMultipleReads) { + constexpr std::string_view kModule = R"(#![feature(explicit_state_access)] +proc main { + init { (0, 1) } + config() { } + next(state_0: u32, state_1: u32) { + let b_0 = read(state_1); + let b_1 = read(state_1); + } +} +)"; + XLS_ASSERT_OK_AND_ASSIGN(std::string converted, + ConvertModuleForTest(kModule)); + ExpectIr(converted); +} + +TEST_F(IrConverterTest, ExplicitStateAccessMultipleStatesMultipleWrites) { + constexpr std::string_view kModule = R"(#![feature(explicit_state_access)] +proc main { + init { (0, 1) } + config() { } + next(state_0: u32, state_1: u32) { + let a = read(state_0); + let b = read(state_1); + write(state_1, a + b); + write(state_1, a + 1); + } +} +)"; + XLS_ASSERT_OK_AND_ASSIGN(std::string converted, + ConvertModuleForTest(kModule)); + ExpectIr(converted); +} + +TEST_F(IrConverterTest, ExplicitStateAccessMultipleStatesWriteBeforeRead) { + constexpr std::string_view kModule = R"(#![feature(explicit_state_access)] +proc main { + init { (0, 1) } + config() { } + next(state_0: u32, state_1: u32) { + let a = read(state_0); + write(state_1, a); + } +} +)"; + XLS_ASSERT_OK_AND_ASSIGN(std::string converted, + ConvertModuleForTest(kModule)); ExpectIr(converted); } diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessArray.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessArray.ir index b10d5c7a95..0ec48fe3b8 100644 --- a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessArray.ir +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessArray.ir @@ -2,45 +2,46 @@ package test_module file_number 0 "test_module.x" -fn ____test_module__Array_0_next_counted_for_0_body(i: bits[3] id=13, __token_wrapped: (token, bits[1], bits[32][4]) id=16) -> (token, bits[1], bits[32][4]) { - literal.14: bits[3] = literal(value=0, id=14) - tuple_index.19: bits[32][4] = tuple_index(__token_wrapped, index=2, id=19) - add.15: bits[3] = add(i, literal.14, id=15) - array_index.20: bits[32] = array_index(tuple_index.19, indices=[add.15], id=20) - literal.21: bits[32] = literal(value=1, id=21) - add.22: bits[32] = add(array_index.20, literal.21, id=22) - tuple_index.17: token = tuple_index(__token_wrapped, index=0, id=17) - tuple_index.18: bits[1] = tuple_index(__token_wrapped, index=1, id=18) - array_update.23: bits[32][4] = array_update(tuple_index.19, add.22, indices=[add.15], id=23) - ret tuple.24: (token, bits[1], bits[32][4]) = tuple(tuple_index.17, tuple_index.18, array_update.23, id=24) +fn ____test_module__Array_0_next_counted_for_0_body(i: bits[3] id=14, __token_wrapped: (token, bits[1], bits[32][4]) id=17) -> (token, bits[1], bits[32][4]) { + literal.15: bits[3] = literal(value=0, id=15) + tuple_index.20: bits[32][4] = tuple_index(__token_wrapped, index=2, id=20) + add.16: bits[3] = add(i, literal.15, id=16) + array_index.21: bits[32] = array_index(tuple_index.20, indices=[add.16], id=21) + literal.22: bits[32] = literal(value=1, id=22) + add.23: bits[32] = add(array_index.21, literal.22, id=23) + tuple_index.18: token = tuple_index(__token_wrapped, index=0, id=18) + tuple_index.19: bits[1] = tuple_index(__token_wrapped, index=1, id=19) + array_update.24: bits[32][4] = array_update(tuple_index.20, add.23, indices=[add.16], id=24) + ret tuple.25: (token, bits[1], bits[32][4]) = tuple(tuple_index.18, tuple_index.19, array_update.24, id=25) } -top proc __test_module__Array_0_next<>(__state: bits[32][4], init={[0, 1, 2, 3]}) { - literal.5: bits[1] = literal(value=1, id=5) +top proc __test_module__Array_0_next<>(__state: bits[32][4], state: bits[32][4], init={[0, 1, 2, 3], [0, 1, 2, 3]}) { + literal.6: bits[1] = literal(value=1, id=6) literal.3: bits[1] = literal(value=0, id=3) - not.7: bits[1] = not(literal.5, id=7) - not.8: bits[1] = not(literal.3, id=8) + not.8: bits[1] = not(literal.6, id=8) + not.9: bits[1] = not(literal.3, id=9) __token: token = literal(value=token, id=1) - or.9: bits[1] = or(not.7, not.8, id=9) - __state: bits[32][4] = state_read(state_element=__state, id=2) - assert.10: token = assert(__token, or.9, message="State element read after read in same activation.", id=10) - array: bits[32][4] = identity(__state, id=12) - not.29: bits[1] = not(literal.5, id=29) - or.11: bits[1] = or(literal.3, literal.5, id=11) + or.10: bits[1] = or(not.8, not.9, id=10) + state: bits[32][4] = state_read(state_element=state, id=5) + assert.11: token = assert(__token, or.10, message="State element read after read in same activation.", id=11) + array: bits[32][4] = identity(state, id=13) + not.30: bits[1] = not(literal.6, id=30) + or.12: bits[1] = or(literal.3, literal.6, id=12) literal.4: bits[1] = literal(value=0, id=4) - tuple.25: (token, bits[1], bits[32][4]) = tuple(assert.10, literal.5, array, id=25) - or.30: bits[1] = or(not.29, or.11, id=30) - not.32: bits[1] = not(literal.5, id=32) - not.33: bits[1] = not(literal.4, id=33) - counted_for.26: (token, bits[1], bits[32][4]) = counted_for(tuple.25, trip_count=4, stride=1, body=____test_module__Array_0_next_counted_for_0_body, id=26) - assert.31: token = assert(assert.10, or.30, message="State element written before read in same activation.", id=31) - or.34: bits[1] = or(not.32, not.33, id=34) - new_array: bits[32][4] = tuple_index(counted_for.26, index=2, id=28) - tuple.6: () = tuple(id=6) - tuple_index.27: token = tuple_index(counted_for.26, index=0, id=27) - assert.35: token = assert(assert.31, or.34, message="State element written after write in same activation.", id=35) - or.36: bits[1] = or(literal.4, literal.5, id=36) - next_value.37: () = next_value(param=__state, value=new_array, predicate=literal.5, id=37) - tuple.38: () = tuple(id=38) + tuple.26: (token, bits[1], bits[32][4]) = tuple(assert.11, literal.6, array, id=26) + or.31: bits[1] = or(not.30, or.12, id=31) + not.33: bits[1] = not(literal.6, id=33) + not.34: bits[1] = not(literal.4, id=34) + counted_for.27: (token, bits[1], bits[32][4]) = counted_for(tuple.26, trip_count=4, stride=1, body=____test_module__Array_0_next_counted_for_0_body, id=27) + assert.32: token = assert(assert.11, or.31, message="State element written before read in same activation.", id=32) + or.35: bits[1] = or(not.33, not.34, id=35) + new_array: bits[32][4] = tuple_index(counted_for.27, index=2, id=29) + __state: bits[32][4] = state_read(state_element=__state, id=2) + tuple.7: () = tuple(id=7) + tuple_index.28: token = tuple_index(counted_for.27, index=0, id=28) + assert.36: token = assert(assert.32, or.35, message="State element written after write in same activation.", id=36) + or.37: bits[1] = or(literal.4, literal.6, id=37) + next_value.38: () = next_value(param=state, value=new_array, predicate=literal.6, id=38) tuple.39: () = tuple(id=39) + tuple.40: () = tuple(id=40) } diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessBool.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessBool.ir index 73761d150c..1c80c8194e 100644 --- a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessBool.ir +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessBool.ir @@ -2,29 +2,30 @@ package test_module file_number 0 "test_module.x" -top proc __test_module__Bool_0_next<>(__state: bits[1], init={0}) { - literal.5: bits[1] = literal(value=1, id=5) +top proc __test_module__Bool_0_next<>(__state: bits[1], state: bits[1], init={0, 0}) { + literal.6: bits[1] = literal(value=1, id=6) literal.3: bits[1] = literal(value=0, id=3) - not.7: bits[1] = not(literal.5, id=7) - not.8: bits[1] = not(literal.3, id=8) + not.8: bits[1] = not(literal.6, id=8) + not.9: bits[1] = not(literal.3, id=9) __token: token = literal(value=token, id=1) - or.9: bits[1] = or(not.7, not.8, id=9) - not.14: bits[1] = not(literal.5, id=14) - or.11: bits[1] = or(literal.3, literal.5, id=11) + or.10: bits[1] = or(not.8, not.9, id=10) + not.15: bits[1] = not(literal.6, id=15) + or.12: bits[1] = or(literal.3, literal.6, id=12) literal.4: bits[1] = literal(value=0, id=4) - assert.10: token = assert(__token, or.9, message="State element read after read in same activation.", id=10) - or.15: bits[1] = or(not.14, or.11, id=15) - not.17: bits[1] = not(literal.5, id=17) - not.18: bits[1] = not(literal.4, id=18) + assert.11: token = assert(__token, or.10, message="State element read after read in same activation.", id=11) + or.16: bits[1] = or(not.15, or.12, id=16) + not.18: bits[1] = not(literal.6, id=18) + not.19: bits[1] = not(literal.4, id=19) + state: bits[1] = state_read(state_element=state, id=5) + assert.17: token = assert(assert.11, or.16, message="State element written before read in same activation.", id=17) + or.20: bits[1] = or(not.18, not.19, id=20) + literal.14: bits[1] = literal(value=1, id=14) __state: bits[1] = state_read(state_element=__state, id=2) - assert.16: token = assert(assert.10, or.15, message="State element written before read in same activation.", id=16) - or.19: bits[1] = or(not.17, not.18, id=19) - literal.13: bits[1] = literal(value=1, id=13) - tuple.6: () = tuple(id=6) - false_val: bits[1] = identity(__state, id=12) - assert.20: token = assert(assert.16, or.19, message="State element written after write in same activation.", id=20) - or.21: bits[1] = or(literal.4, literal.5, id=21) - next_value.22: () = next_value(param=__state, value=literal.13, predicate=literal.5, id=22) - tuple.23: () = tuple(id=23) + tuple.7: () = tuple(id=7) + false_val: bits[1] = identity(state, id=13) + assert.21: token = assert(assert.17, or.20, message="State element written after write in same activation.", id=21) + or.22: bits[1] = or(literal.4, literal.6, id=22) + next_value.23: () = next_value(param=state, value=literal.14, predicate=literal.6, id=23) tuple.24: () = tuple(id=24) + tuple.25: () = tuple(id=25) } diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessConditionalWrite.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessConditionalWrite.ir index 40dea1f1ac..8dcd9cfecf 100644 --- a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessConditionalWrite.ir +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessConditionalWrite.ir @@ -2,59 +2,60 @@ package test_module file_number 0 "test_module.x" -top proc __test_module__main_0_next<>(__state: (bits[32], bits[1]), init={(0, 0)}) { - __state: (bits[32], bits[1]) = state_read(state_element=__state, id=2) - even_or_odd: (bits[32], bits[1]) = identity(__state, id=12) - tuple_index.14: bits[32] = tuple_index(even_or_odd, index=0, id=14) - literal.15: bits[32] = literal(value=2, id=15) - umod.16: bits[32] = umod(tuple_index.14, literal.15, id=16) - literal.17: bits[32] = literal(value=0, id=17) - literal.5: bits[1] = literal(value=1, id=5) +top proc __test_module__main_0_next<>(__state: (bits[32], bits[1]), state: (bits[32], bits[1]), init={(0, 0), (0, 0)}) { + state: (bits[32], bits[1]) = state_read(state_element=state, id=5) + even_or_odd: (bits[32], bits[1]) = identity(state, id=13) + tuple_index.15: bits[32] = tuple_index(even_or_odd, index=0, id=15) + literal.16: bits[32] = literal(value=2, id=16) + umod.17: bits[32] = umod(tuple_index.15, literal.16, id=17) + literal.18: bits[32] = literal(value=0, id=18) + literal.6: bits[1] = literal(value=1, id=6) literal.3: bits[1] = literal(value=0, id=3) - eq.18: bits[1] = eq(umod.16, literal.17, id=18) - not.7: bits[1] = not(literal.5, id=7) - not.8: bits[1] = not(literal.3, id=8) - and.25: bits[1] = and(literal.5, eq.18, id=25) + eq.19: bits[1] = eq(umod.17, literal.18, id=19) + not.8: bits[1] = not(literal.6, id=8) + not.9: bits[1] = not(literal.3, id=9) + and.26: bits[1] = and(literal.6, eq.19, id=26) __token: token = literal(value=token, id=1) - or.9: bits[1] = or(not.7, not.8, id=9) - not.26: bits[1] = not(and.25, id=26) - or.11: bits[1] = or(literal.3, literal.5, id=11) + or.10: bits[1] = or(not.8, not.9, id=10) + not.27: bits[1] = not(and.26, id=27) + or.12: bits[1] = or(literal.3, literal.6, id=12) literal.4: bits[1] = literal(value=0, id=4) - not.42: bits[1] = not(eq.18, id=42) - assert.10: token = assert(__token, or.9, message="State element read after read in same activation.", id=10) - or.27: bits[1] = or(not.26, or.11, id=27) - not.29: bits[1] = not(and.25, id=29) - not.30: bits[1] = not(literal.4, id=30) - and.43: bits[1] = and(literal.5, not.42, id=43) - tuple_index.20: bits[32] = tuple_index(even_or_odd, index=0, id=20) - literal.21: bits[32] = literal(value=1, id=21) - assert.28: token = assert(assert.10, or.27, message="State element written before read in same activation.", id=28) - or.31: bits[1] = or(not.29, not.30, id=31) - not.44: bits[1] = not(and.43, id=44) - or.33: bits[1] = or(literal.4, and.25, id=33) - tuple_index.37: bits[32] = tuple_index(even_or_odd, index=0, id=37) - literal.38: bits[32] = literal(value=1, id=38) - add.22: bits[32] = add(tuple_index.20, literal.21, id=22) - literal.23: bits[1] = literal(value=1, id=23) - assert.32: token = assert(assert.28, or.31, message="State element written after write in same activation.", id=32) - or.45: bits[1] = or(not.44, or.11, id=45) - not.47: bits[1] = not(and.43, id=47) - not.48: bits[1] = not(or.33, id=48) - add.39: bits[32] = add(tuple_index.37, literal.38, id=39) - literal.40: bits[1] = literal(value=0, id=40) - tuple.24: (bits[32], bits[1]) = tuple(add.22, literal.23, id=24) - assert.46: token = assert(assert.32, or.45, message="State element written before read in same activation.", id=46) - or.49: bits[1] = or(not.47, not.48, id=49) - tuple.41: (bits[32], bits[1]) = tuple(add.39, literal.40, id=41) - tuple.53: () = tuple(id=53) - tuple.35: () = tuple(id=35) - tuple.6: () = tuple(id=6) - literal.13: bits[32] = literal(value=0, id=13) - literal.19: bits[32] = literal(value=0, id=19) - next_value.34: () = next_value(param=__state, value=tuple.24, predicate=and.25, id=34) - literal.36: bits[32] = literal(value=0, id=36) - assert.50: token = assert(assert.46, or.49, message="State element written after write in same activation.", id=50) - or.51: bits[1] = or(or.33, and.43, id=51) - next_value.52: () = next_value(param=__state, value=tuple.41, predicate=and.43, id=52) - sel.54: () = sel(eq.18, cases=[tuple.53, tuple.35], id=54) + not.43: bits[1] = not(eq.19, id=43) + assert.11: token = assert(__token, or.10, message="State element read after read in same activation.", id=11) + or.28: bits[1] = or(not.27, or.12, id=28) + not.30: bits[1] = not(and.26, id=30) + not.31: bits[1] = not(literal.4, id=31) + and.44: bits[1] = and(literal.6, not.43, id=44) + tuple_index.21: bits[32] = tuple_index(even_or_odd, index=0, id=21) + literal.22: bits[32] = literal(value=1, id=22) + assert.29: token = assert(assert.11, or.28, message="State element written before read in same activation.", id=29) + or.32: bits[1] = or(not.30, not.31, id=32) + not.45: bits[1] = not(and.44, id=45) + or.34: bits[1] = or(literal.4, and.26, id=34) + tuple_index.38: bits[32] = tuple_index(even_or_odd, index=0, id=38) + literal.39: bits[32] = literal(value=1, id=39) + add.23: bits[32] = add(tuple_index.21, literal.22, id=23) + literal.24: bits[1] = literal(value=1, id=24) + assert.33: token = assert(assert.29, or.32, message="State element written after write in same activation.", id=33) + or.46: bits[1] = or(not.45, or.12, id=46) + not.48: bits[1] = not(and.44, id=48) + not.49: bits[1] = not(or.34, id=49) + add.40: bits[32] = add(tuple_index.38, literal.39, id=40) + literal.41: bits[1] = literal(value=0, id=41) + tuple.25: (bits[32], bits[1]) = tuple(add.23, literal.24, id=25) + assert.47: token = assert(assert.33, or.46, message="State element written before read in same activation.", id=47) + or.50: bits[1] = or(not.48, not.49, id=50) + tuple.42: (bits[32], bits[1]) = tuple(add.40, literal.41, id=42) + tuple.54: () = tuple(id=54) + tuple.36: () = tuple(id=36) + __state: (bits[32], bits[1]) = state_read(state_element=__state, id=2) + tuple.7: () = tuple(id=7) + literal.14: bits[32] = literal(value=0, id=14) + literal.20: bits[32] = literal(value=0, id=20) + next_value.35: () = next_value(param=state, value=tuple.25, predicate=and.26, id=35) + literal.37: bits[32] = literal(value=0, id=37) + assert.51: token = assert(assert.47, or.50, message="State element written after write in same activation.", id=51) + or.52: bits[1] = or(or.34, and.44, id=52) + next_value.53: () = next_value(param=state, value=tuple.42, predicate=and.44, id=53) + sel.55: () = sel(eq.19, cases=[tuple.54, tuple.36], id=55) } diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessLabeledReadAndWrite.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessLabeledReadAndWrite.ir new file mode 100644 index 0000000000..39072a46f8 --- /dev/null +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessLabeledReadAndWrite.ir @@ -0,0 +1,32 @@ +package test_module + +file_number 0 "test_module.x" + +top proc __test_module__main_0_next<>(__state: bits[32], state: bits[32], init={0, 0}) { + literal.6: bits[1] = literal(value=1, id=6) + literal.3: bits[1] = literal(value=0, id=3) + not.8: bits[1] = not(literal.6, id=8) + not.9: bits[1] = not(literal.3, id=9) + __token: token = literal(value=token, id=1) + or.10: bits[1] = or(not.8, not.9, id=10) + not.16: bits[1] = not(literal.6, id=16) + or.12: bits[1] = or(literal.3, literal.6, id=12) + literal.4: bits[1] = literal(value=0, id=4) + state: bits[32] = state_read(state_element=state, label="main_read", id=5) + assert.11: token = assert(__token, or.10, message="State element read after read in same activation.", id=11) + or.17: bits[1] = or(not.16, or.12, id=17) + not.19: bits[1] = not(literal.6, id=19) + not.20: bits[1] = not(literal.4, id=20) + x: bits[32] = identity(state, id=13) + literal.14: bits[32] = literal(value=1, id=14) + assert.18: token = assert(assert.11, or.17, message="State element written before read in same activation.", id=18) + or.21: bits[1] = or(not.19, not.20, id=21) + y: bits[32] = add(x, literal.14, id=15) + __state: bits[32] = state_read(state_element=__state, id=2) + tuple.7: () = tuple(id=7) + assert.22: token = assert(assert.18, or.21, message="State element written after write in same activation.", id=22) + or.23: bits[1] = or(literal.4, literal.6, id=23) + next_value.24: () = next_value(param=state, value=y, predicate=literal.6, label="main_write", id=24) + tuple.25: () = tuple(id=25) + tuple.26: () = tuple(id=26) +} diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMatch.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMatch.ir index 2430c961fb..c4c7499e8f 100644 --- a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMatch.ir +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMatch.ir @@ -2,69 +2,70 @@ package test_module file_number 0 "test_module.x" -top proc __test_module__main_0_next<>(__state: bits[32], init={0}) { - __state: bits[32] = state_read(state_element=__state, id=2) - current: bits[32] = identity(__state, id=12) - literal.13: bits[32] = literal(value=2, id=13) - literal.15: bits[32] = literal(value=0, id=15) - even_or_odd: bits[32] = umod(current, literal.13, id=14) - literal.5: bits[1] = literal(value=1, id=5) +top proc __test_module__main_0_next<>(__state: bits[32], state: bits[32], init={0, 0}) { + state: bits[32] = state_read(state_element=state, id=5) + current: bits[32] = identity(state, id=13) + literal.14: bits[32] = literal(value=2, id=14) + literal.16: bits[32] = literal(value=0, id=16) + even_or_odd: bits[32] = umod(current, literal.14, id=15) + literal.6: bits[1] = literal(value=1, id=6) literal.3: bits[1] = literal(value=0, id=3) - literal.19: bits[1] = literal(value=1, id=19) - eq.16: bits[1] = eq(literal.15, even_or_odd, id=16) - not.7: bits[1] = not(literal.5, id=7) - not.8: bits[1] = not(literal.3, id=8) - and.20: bits[1] = and(literal.5, literal.19, eq.16, id=20) - literal.32: bits[32] = literal(value=1, id=32) + literal.20: bits[1] = literal(value=1, id=20) + eq.17: bits[1] = eq(literal.16, even_or_odd, id=17) + not.8: bits[1] = not(literal.6, id=8) + not.9: bits[1] = not(literal.3, id=9) + and.21: bits[1] = and(literal.6, literal.20, eq.17, id=21) + literal.33: bits[32] = literal(value=1, id=33) __token: token = literal(value=token, id=1) - or.9: bits[1] = or(not.7, not.8, id=9) - not.21: bits[1] = not(and.20, id=21) - or.11: bits[1] = or(literal.3, literal.5, id=11) + or.10: bits[1] = or(not.8, not.9, id=10) + not.22: bits[1] = not(and.21, id=22) + or.12: bits[1] = or(literal.3, literal.6, id=12) literal.4: bits[1] = literal(value=0, id=4) - not.36: bits[1] = not(eq.16, id=36) - eq.33: bits[1] = eq(literal.32, even_or_odd, id=33) - assert.10: token = assert(__token, or.9, message="State element read after read in same activation.", id=10) - or.22: bits[1] = or(not.21, or.11, id=22) - not.24: bits[1] = not(and.20, id=24) - not.25: bits[1] = not(literal.4, id=25) - and.37: bits[1] = and(literal.5, not.36, eq.33, id=37) - assert.23: token = assert(assert.10, or.22, message="State element written before read in same activation.", id=23) - or.26: bits[1] = or(not.24, not.25, id=26) - not.38: bits[1] = not(and.37, id=38) - or.28: bits[1] = or(literal.4, and.20, id=28) - nor.50: bits[1] = nor(eq.16, eq.33, id=50) - assert.27: token = assert(assert.23, or.26, message="State element written after write in same activation.", id=27) - or.39: bits[1] = or(not.38, or.11, id=39) - not.41: bits[1] = not(and.37, id=41) - not.42: bits[1] = not(or.28, id=42) - and.51: bits[1] = and(literal.5, nor.50, id=51) - assert.40: token = assert(assert.27, or.39, message="State element written before read in same activation.", id=40) - or.43: bits[1] = or(not.41, not.42, id=43) - not.52: bits[1] = not(and.51, id=52) - or.45: bits[1] = or(or.28, and.37, id=45) - literal.17: bits[32] = literal(value=1, id=17) - literal.34: bits[32] = literal(value=2, id=34) - assert.44: token = assert(assert.40, or.43, message="State element written after write in same activation.", id=44) - or.53: bits[1] = or(not.52, or.11, id=53) - not.55: bits[1] = not(and.51, id=55) - not.56: bits[1] = not(or.45, id=56) - add.18: bits[32] = add(current, literal.17, id=18) - umul.35: bits[32] = umul(current, literal.34, id=35) - assert.54: token = assert(assert.44, or.53, message="State element written before read in same activation.", id=54) - or.57: bits[1] = or(not.55, not.56, id=57) - concat.63: bits[2] = concat(eq.33, eq.16, id=63) + not.37: bits[1] = not(eq.17, id=37) + eq.34: bits[1] = eq(literal.33, even_or_odd, id=34) + assert.11: token = assert(__token, or.10, message="State element read after read in same activation.", id=11) + or.23: bits[1] = or(not.22, or.12, id=23) + not.25: bits[1] = not(and.21, id=25) + not.26: bits[1] = not(literal.4, id=26) + and.38: bits[1] = and(literal.6, not.37, eq.34, id=38) + assert.24: token = assert(assert.11, or.23, message="State element written before read in same activation.", id=24) + or.27: bits[1] = or(not.25, not.26, id=27) + not.39: bits[1] = not(and.38, id=39) + or.29: bits[1] = or(literal.4, and.21, id=29) + nor.51: bits[1] = nor(eq.17, eq.34, id=51) + assert.28: token = assert(assert.24, or.27, message="State element written after write in same activation.", id=28) + or.40: bits[1] = or(not.39, or.12, id=40) + not.42: bits[1] = not(and.38, id=42) + not.43: bits[1] = not(or.29, id=43) + and.52: bits[1] = and(literal.6, nor.51, id=52) + assert.41: token = assert(assert.28, or.40, message="State element written before read in same activation.", id=41) + or.44: bits[1] = or(not.42, not.43, id=44) + not.53: bits[1] = not(and.52, id=53) + or.46: bits[1] = or(or.29, and.38, id=46) + literal.18: bits[32] = literal(value=1, id=18) + literal.35: bits[32] = literal(value=2, id=35) + assert.45: token = assert(assert.41, or.44, message="State element written after write in same activation.", id=45) + or.54: bits[1] = or(not.53, or.12, id=54) + not.56: bits[1] = not(and.52, id=56) + not.57: bits[1] = not(or.46, id=57) + add.19: bits[32] = add(current, literal.18, id=19) + umul.36: bits[32] = umul(current, literal.35, id=36) + assert.55: token = assert(assert.45, or.54, message="State element written before read in same activation.", id=55) + or.58: bits[1] = or(not.56, not.57, id=58) + concat.64: bits[2] = concat(eq.34, eq.17, id=64) + tuple.32: () = tuple(id=32) + tuple.49: () = tuple(id=49) + tuple.63: () = tuple(id=63) + __state: bits[32] = state_read(state_element=__state, id=2) + tuple.7: () = tuple(id=7) + next_value.30: () = next_value(param=state, value=add.19, predicate=and.21, id=30) tuple.31: () = tuple(id=31) + next_value.47: () = next_value(param=state, value=umul.36, predicate=and.38, id=47) tuple.48: () = tuple(id=48) + literal.50: bits[1] = literal(value=1, id=50) + assert.59: token = assert(assert.55, or.58, message="State element written after write in same activation.", id=59) + or.60: bits[1] = or(or.46, and.52, id=60) + next_value.61: () = next_value(param=state, value=current, predicate=and.52, id=61) tuple.62: () = tuple(id=62) - tuple.6: () = tuple(id=6) - next_value.29: () = next_value(param=__state, value=add.18, predicate=and.20, id=29) - tuple.30: () = tuple(id=30) - next_value.46: () = next_value(param=__state, value=umul.35, predicate=and.37, id=46) - tuple.47: () = tuple(id=47) - literal.49: bits[1] = literal(value=1, id=49) - assert.58: token = assert(assert.54, or.57, message="State element written after write in same activation.", id=58) - or.59: bits[1] = or(or.45, and.51, id=59) - next_value.60: () = next_value(param=__state, value=current, predicate=and.51, id=60) - tuple.61: () = tuple(id=61) - priority_sel.64: () = priority_sel(concat.63, cases=[tuple.31, tuple.48], default=tuple.62, id=64) + priority_sel.65: () = priority_sel(concat.64, cases=[tuple.32, tuple.49], default=tuple.63, id=65) } diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMatchMultipleWrites.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMatchMultipleWrites.ir index eea3c33520..1ee998b91c 100644 --- a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMatchMultipleWrites.ir +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMatchMultipleWrites.ir @@ -2,77 +2,78 @@ package test_module file_number 0 "test_module.x" -top proc __test_module__main_0_next<>(__state: bits[1], init={1}) { - __state: bits[1] = state_read(state_element=__state, id=2) - literal.13: bits[1] = literal(value=1, id=13) - val: bits[1] = identity(__state, id=12) - literal.5: bits[1] = literal(value=1, id=5) +top proc __test_module__main_0_next<>(__state: bits[1], state: bits[1], init={1, 1}) { + state: bits[1] = state_read(state_element=state, id=5) + literal.14: bits[1] = literal(value=1, id=14) + val: bits[1] = identity(state, id=13) + literal.6: bits[1] = literal(value=1, id=6) literal.3: bits[1] = literal(value=0, id=3) - literal.16: bits[1] = literal(value=1, id=16) - eq.14: bits[1] = eq(literal.13, val, id=14) - not.7: bits[1] = not(literal.5, id=7) - not.8: bits[1] = not(literal.3, id=8) - and.17: bits[1] = and(literal.5, literal.16, eq.14, id=17) + literal.17: bits[1] = literal(value=1, id=17) + eq.15: bits[1] = eq(literal.14, val, id=15) + not.8: bits[1] = not(literal.6, id=8) + not.9: bits[1] = not(literal.3, id=9) + and.18: bits[1] = and(literal.6, literal.17, eq.15, id=18) __token: token = literal(value=token, id=1) - or.9: bits[1] = or(not.7, not.8, id=9) - not.18: bits[1] = not(and.17, id=18) - or.11: bits[1] = or(literal.3, literal.5, id=11) + or.10: bits[1] = or(not.8, not.9, id=10) + not.19: bits[1] = not(and.18, id=19) + or.12: bits[1] = or(literal.3, literal.6, id=12) literal.4: bits[1] = literal(value=0, id=4) - literal.29: bits[1] = literal(value=1, id=29) - assert.10: token = assert(__token, or.9, message="State element read after read in same activation.", id=10) - or.19: bits[1] = or(not.18, or.11, id=19) - not.21: bits[1] = not(and.17, id=21) - not.22: bits[1] = not(literal.4, id=22) - and.30: bits[1] = and(literal.5, literal.29, eq.14, id=30) - assert.20: token = assert(assert.10, or.19, message="State element written before read in same activation.", id=20) - or.23: bits[1] = or(not.21, not.22, id=23) - not.31: bits[1] = not(and.30, id=31) - or.25: bits[1] = or(literal.4, and.17, id=25) - not.45: bits[1] = not(eq.14, id=45) - assert.24: token = assert(assert.20, or.23, message="State element written after write in same activation.", id=24) - or.32: bits[1] = or(not.31, or.11, id=32) - not.34: bits[1] = not(and.30, id=34) - not.35: bits[1] = not(or.25, id=35) - and.46: bits[1] = and(literal.5, not.45, id=46) - assert.33: token = assert(assert.24, or.32, message="State element written before read in same activation.", id=33) - or.36: bits[1] = or(not.34, not.35, id=36) - not.47: bits[1] = not(and.46, id=47) - or.38: bits[1] = or(or.25, and.30, id=38) - not.58: bits[1] = not(eq.14, id=58) - assert.37: token = assert(assert.33, or.36, message="State element written after write in same activation.", id=37) - or.48: bits[1] = or(not.47, or.11, id=48) - not.50: bits[1] = not(and.46, id=50) - not.51: bits[1] = not(or.38, id=51) - and.59: bits[1] = and(literal.5, not.58, id=59) - assert.49: token = assert(assert.37, or.48, message="State element written before read in same activation.", id=49) - or.52: bits[1] = or(not.50, not.51, id=52) - not.60: bits[1] = not(and.59, id=60) - or.54: bits[1] = or(or.38, and.46, id=54) - assert.53: token = assert(assert.49, or.52, message="State element written after write in same activation.", id=53) - or.61: bits[1] = or(not.60, or.11, id=61) - not.63: bits[1] = not(and.59, id=63) - not.64: bits[1] = not(or.54, id=64) - literal.15: bits[1] = literal(value=0, id=15) - literal.28: bits[1] = literal(value=0, id=28) - literal.42: bits[1] = literal(value=0, id=42) - literal.44: bits[1] = literal(value=1, id=44) - assert.62: token = assert(assert.53, or.61, message="State element written before read in same activation.", id=62) - or.65: bits[1] = or(not.63, not.64, id=65) - literal.57: bits[1] = literal(value=1, id=57) - concat.71: bits[1] = concat(eq.14, id=71) + literal.30: bits[1] = literal(value=1, id=30) + assert.11: token = assert(__token, or.10, message="State element read after read in same activation.", id=11) + or.20: bits[1] = or(not.19, or.12, id=20) + not.22: bits[1] = not(and.18, id=22) + not.23: bits[1] = not(literal.4, id=23) + and.31: bits[1] = and(literal.6, literal.30, eq.15, id=31) + assert.21: token = assert(assert.11, or.20, message="State element written before read in same activation.", id=21) + or.24: bits[1] = or(not.22, not.23, id=24) + not.32: bits[1] = not(and.31, id=32) + or.26: bits[1] = or(literal.4, and.18, id=26) + not.46: bits[1] = not(eq.15, id=46) + assert.25: token = assert(assert.21, or.24, message="State element written after write in same activation.", id=25) + or.33: bits[1] = or(not.32, or.12, id=33) + not.35: bits[1] = not(and.31, id=35) + not.36: bits[1] = not(or.26, id=36) + and.47: bits[1] = and(literal.6, not.46, id=47) + assert.34: token = assert(assert.25, or.33, message="State element written before read in same activation.", id=34) + or.37: bits[1] = or(not.35, not.36, id=37) + not.48: bits[1] = not(and.47, id=48) + or.39: bits[1] = or(or.26, and.31, id=39) + not.59: bits[1] = not(eq.15, id=59) + assert.38: token = assert(assert.34, or.37, message="State element written after write in same activation.", id=38) + or.49: bits[1] = or(not.48, or.12, id=49) + not.51: bits[1] = not(and.47, id=51) + not.52: bits[1] = not(or.39, id=52) + and.60: bits[1] = and(literal.6, not.59, id=60) + assert.50: token = assert(assert.38, or.49, message="State element written before read in same activation.", id=50) + or.53: bits[1] = or(not.51, not.52, id=53) + not.61: bits[1] = not(and.60, id=61) + or.55: bits[1] = or(or.39, and.47, id=55) + assert.54: token = assert(assert.50, or.53, message="State element written after write in same activation.", id=54) + or.62: bits[1] = or(not.61, or.12, id=62) + not.64: bits[1] = not(and.60, id=64) + not.65: bits[1] = not(or.55, id=65) + literal.16: bits[1] = literal(value=0, id=16) + literal.29: bits[1] = literal(value=0, id=29) + literal.43: bits[1] = literal(value=0, id=43) + literal.45: bits[1] = literal(value=1, id=45) + assert.63: token = assert(assert.54, or.62, message="State element written before read in same activation.", id=63) + or.66: bits[1] = or(not.64, not.65, id=66) + literal.58: bits[1] = literal(value=1, id=58) + concat.72: bits[1] = concat(eq.15, id=72) + tuple.42: () = tuple(id=42) + tuple.71: () = tuple(id=71) + __state: bits[1] = state_read(state_element=__state, id=2) + tuple.7: () = tuple(id=7) + next_value.27: () = next_value(param=state, value=literal.16, predicate=and.18, id=27) + tuple.28: () = tuple(id=28) + next_value.40: () = next_value(param=state, value=literal.29, predicate=and.31, id=40) tuple.41: () = tuple(id=41) + eq.44: bits[1] = eq(literal.43, val, id=44) + next_value.56: () = next_value(param=state, value=literal.45, predicate=and.47, id=56) + tuple.57: () = tuple(id=57) + assert.67: token = assert(assert.63, or.66, message="State element written after write in same activation.", id=67) + or.68: bits[1] = or(or.55, and.60, id=68) + next_value.69: () = next_value(param=state, value=literal.58, predicate=and.60, id=69) tuple.70: () = tuple(id=70) - tuple.6: () = tuple(id=6) - next_value.26: () = next_value(param=__state, value=literal.15, predicate=and.17, id=26) - tuple.27: () = tuple(id=27) - next_value.39: () = next_value(param=__state, value=literal.28, predicate=and.30, id=39) - tuple.40: () = tuple(id=40) - eq.43: bits[1] = eq(literal.42, val, id=43) - next_value.55: () = next_value(param=__state, value=literal.44, predicate=and.46, id=55) - tuple.56: () = tuple(id=56) - assert.66: token = assert(assert.62, or.65, message="State element written after write in same activation.", id=66) - or.67: bits[1] = or(or.54, and.59, id=67) - next_value.68: () = next_value(param=__state, value=literal.57, predicate=and.59, id=68) - tuple.69: () = tuple(id=69) - priority_sel.72: () = priority_sel(concat.71, cases=[tuple.41], default=tuple.70, id=72) + priority_sel.73: () = priority_sel(concat.72, cases=[tuple.42], default=tuple.71, id=73) } diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleReads.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleReads.ir index 47146655bb..76f84a2336 100644 --- a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleReads.ir +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleReads.ir @@ -2,24 +2,25 @@ package test_module file_number 0 "test_module.x" -top proc __test_module__main_0_next<>(__state: bits[32], init={0}) { - literal.5: bits[1] = literal(value=1, id=5) +top proc __test_module__main_0_next<>(__state: bits[32], state: bits[32], init={0, 0}) { + literal.6: bits[1] = literal(value=1, id=6) literal.3: bits[1] = literal(value=0, id=3) - not.7: bits[1] = not(literal.5, id=7) - not.8: bits[1] = not(literal.3, id=8) - or.11: bits[1] = or(literal.3, literal.5, id=11) + not.8: bits[1] = not(literal.6, id=8) + not.9: bits[1] = not(literal.3, id=9) + or.12: bits[1] = or(literal.3, literal.6, id=12) __token: token = literal(value=token, id=1) - or.9: bits[1] = or(not.7, not.8, id=9) - not.13: bits[1] = not(literal.5, id=13) - not.14: bits[1] = not(or.11, id=14) + or.10: bits[1] = or(not.8, not.9, id=10) + not.14: bits[1] = not(literal.6, id=14) + not.15: bits[1] = not(or.12, id=15) + state: bits[32] = state_read(state_element=state, id=5) + assert.11: token = assert(__token, or.10, message="State element read after read in same activation.", id=11) + or.16: bits[1] = or(not.14, not.15, id=16) __state: bits[32] = state_read(state_element=__state, id=2) - assert.10: token = assert(__token, or.9, message="State element read after read in same activation.", id=10) - or.15: bits[1] = or(not.13, not.14, id=15) literal.4: bits[1] = literal(value=0, id=4) - tuple.6: () = tuple(id=6) - first: bits[32] = identity(__state, id=12) - assert.16: token = assert(assert.10, or.15, message="State element read after read in same activation.", id=16) - or.17: bits[1] = or(or.11, literal.5, id=17) - second: bits[32] = identity(__state, id=18) - tuple.19: () = tuple(id=19) + tuple.7: () = tuple(id=7) + first: bits[32] = identity(state, id=13) + assert.17: token = assert(assert.11, or.16, message="State element read after read in same activation.", id=17) + or.18: bits[1] = or(or.12, literal.6, id=18) + second: bits[32] = identity(state, id=19) + tuple.20: () = tuple(id=20) } diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleStates.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleStates.ir new file mode 100644 index 0000000000..1cf875ee03 --- /dev/null +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleStates.ir @@ -0,0 +1,84 @@ +package test_module + +file_number 0 "test_module.x" + +top proc __test_module__main_0_next<>(__state: ((bits[32], bits[32]), (bits[32], bits[32]), bits[32]), state_0: (bits[32], bits[32]), state_1: (bits[32], bits[32]), state_2: bits[32], init={((0, 1), (2, 3), 4), (0, 1), (2, 3), 4}) { + literal.12: bits[1] = literal(value=1, id=12) + literal.3: bits[1] = literal(value=0, id=3) + not.14: bits[1] = not(literal.12, id=14) + not.15: bits[1] = not(literal.3, id=15) + literal.5: bits[1] = literal(value=0, id=5) + __token: token = literal(value=token, id=1) + or.16: bits[1] = or(not.14, not.15, id=16) + not.20: bits[1] = not(literal.12, id=20) + not.21: bits[1] = not(literal.5, id=21) + literal.7: bits[1] = literal(value=0, id=7) + assert.17: token = assert(__token, or.16, message="State element read after read in same activation.", id=17) + or.22: bits[1] = or(not.20, not.21, id=22) + not.26: bits[1] = not(literal.12, id=26) + not.27: bits[1] = not(literal.7, id=27) + assert.23: token = assert(assert.17, or.22, message="State element read after read in same activation.", id=23) + or.28: bits[1] = or(not.26, not.27, id=28) + not.46: bits[1] = not(literal.12, id=46) + or.18: bits[1] = or(literal.3, literal.12, id=18) + literal.4: bits[1] = literal(value=0, id=4) + assert.29: token = assert(assert.23, or.28, message="State element read after read in same activation.", id=29) + or.47: bits[1] = or(not.46, or.18, id=47) + not.49: bits[1] = not(literal.12, id=49) + not.50: bits[1] = not(literal.4, id=50) + state_0: (bits[32], bits[32]) = state_read(state_element=state_0, id=9) + state_1: (bits[32], bits[32]) = state_read(state_element=state_1, id=10) + assert.48: token = assert(assert.29, or.47, message="State element written before read in same activation.", id=48) + or.51: bits[1] = or(not.49, not.50, id=51) + not.56: bits[1] = not(literal.12, id=56) + or.24: bits[1] = or(literal.5, literal.12, id=24) + literal.6: bits[1] = literal(value=0, id=6) + a: (bits[32], bits[32]) = identity(state_0, id=19) + b: (bits[32], bits[32]) = identity(state_1, id=25) + state_2: bits[32] = state_read(state_element=state_2, id=11) + assert.52: token = assert(assert.48, or.51, message="State element written after write in same activation.", id=52) + or.57: bits[1] = or(not.56, or.24, id=57) + not.59: bits[1] = not(literal.12, id=59) + not.60: bits[1] = not(literal.6, id=60) + a_x: bits[32] = tuple_index(a, index=0, id=32) + literal.33: bits[32] = literal(value=1, id=33) + tuple_index.36: bits[32] = tuple_index(b, index=1, id=36) + c: bits[32] = identity(state_2, id=31) + tuple_index.40: bits[32] = tuple_index(b, index=0, id=40) + literal.41: bits[32] = literal(value=1, id=41) + literal.43: bits[32] = literal(value=1, id=43) + assert.58: token = assert(assert.52, or.57, message="State element written before read in same activation.", id=58) + or.61: bits[1] = or(not.59, not.60, id=61) + not.68: bits[1] = not(literal.12, id=68) + or.30: bits[1] = or(literal.7, literal.12, id=30) + literal.8: bits[1] = literal(value=0, id=8) + add.34: bits[32] = add(a_x, literal.33, id=34) + add.37: bits[32] = add(tuple_index.36, c, id=37) + add.42: bits[32] = add(tuple_index.40, literal.41, id=42) + add.44: bits[32] = add(c, literal.43, id=44) + assert.62: token = assert(assert.58, or.61, message="State element written after write in same activation.", id=62) + or.69: bits[1] = or(not.68, or.30, id=69) + not.71: bits[1] = not(literal.12, id=71) + not.72: bits[1] = not(literal.8, id=72) + literal.66: bits[32] = literal(value=2, id=66) + new_a: (bits[32], bits[32]) = tuple(add.34, add.37, id=38) + new_b: (bits[32], bits[32]) = tuple(add.42, add.44, id=45) + assert.70: token = assert(assert.62, or.69, message="State element written before read in same activation.", id=70) + or.73: bits[1] = or(not.71, not.72, id=73) + add.67: bits[32] = add(c, literal.66, id=67) + __state: ((bits[32], bits[32]), (bits[32], bits[32]), bits[32]) = state_read(state_element=__state, id=2) + tuple.13: () = tuple(id=13) + literal.35: bits[32] = literal(value=1, id=35) + literal.39: bits[32] = literal(value=0, id=39) + or.53: bits[1] = or(literal.4, literal.12, id=53) + next_value.54: () = next_value(param=state_0, value=new_a, predicate=literal.12, id=54) + tuple.55: () = tuple(id=55) + or.63: bits[1] = or(literal.6, literal.12, id=63) + next_value.64: () = next_value(param=state_1, value=new_b, predicate=literal.12, id=64) + tuple.65: () = tuple(id=65) + assert.74: token = assert(assert.70, or.73, message="State element written after write in same activation.", id=74) + or.75: bits[1] = or(literal.8, literal.12, id=75) + next_value.76: () = next_value(param=state_2, value=add.67, predicate=literal.12, id=76) + tuple.77: () = tuple(id=77) + tuple.78: () = tuple(id=78) +} diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleStatesMultipleReads.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleStatesMultipleReads.ir new file mode 100644 index 0000000000..3e1a16eeda --- /dev/null +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleStatesMultipleReads.ir @@ -0,0 +1,29 @@ +package test_module + +file_number 0 "test_module.x" + +top proc __test_module__main_0_next<>(__state: (bits[32], bits[32]), state_0: bits[32], state_1: bits[32], init={(0, 1), 0, 1}) { + literal.9: bits[1] = literal(value=1, id=9) + literal.5: bits[1] = literal(value=0, id=5) + not.11: bits[1] = not(literal.9, id=11) + not.12: bits[1] = not(literal.5, id=12) + or.15: bits[1] = or(literal.5, literal.9, id=15) + __token: token = literal(value=token, id=1) + or.13: bits[1] = or(not.11, not.12, id=13) + not.17: bits[1] = not(literal.9, id=17) + not.18: bits[1] = not(or.15, id=18) + state_1: bits[32] = state_read(state_element=state_1, id=8) + assert.14: token = assert(__token, or.13, message="State element read after read in same activation.", id=14) + or.19: bits[1] = or(not.17, not.18, id=19) + __state: (bits[32], bits[32]) = state_read(state_element=__state, id=2) + literal.3: bits[1] = literal(value=0, id=3) + literal.4: bits[1] = literal(value=0, id=4) + literal.6: bits[1] = literal(value=0, id=6) + state_0: bits[32] = state_read(state_element=state_0, id=7) + tuple.10: () = tuple(id=10) + b_0: bits[32] = identity(state_1, id=16) + assert.20: token = assert(assert.14, or.19, message="State element read after read in same activation.", id=20) + or.21: bits[1] = or(or.15, literal.9, id=21) + b_1: bits[32] = identity(state_1, id=22) + tuple.23: () = tuple(id=23) +} diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleStatesMultipleWrites.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleStatesMultipleWrites.ir new file mode 100644 index 0000000000..3fae4d5360 --- /dev/null +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleStatesMultipleWrites.ir @@ -0,0 +1,52 @@ +package test_module + +file_number 0 "test_module.x" + +top proc __test_module__main_0_next<>(__state: (bits[32], bits[32]), state_0: bits[32], state_1: bits[32], init={(0, 1), 0, 1}) { + literal.9: bits[1] = literal(value=1, id=9) + literal.3: bits[1] = literal(value=0, id=3) + not.11: bits[1] = not(literal.9, id=11) + not.12: bits[1] = not(literal.3, id=12) + literal.5: bits[1] = literal(value=0, id=5) + __token: token = literal(value=token, id=1) + or.13: bits[1] = or(not.11, not.12, id=13) + not.17: bits[1] = not(literal.9, id=17) + not.18: bits[1] = not(literal.5, id=18) + assert.14: token = assert(__token, or.13, message="State element read after read in same activation.", id=14) + or.19: bits[1] = or(not.17, not.18, id=19) + not.24: bits[1] = not(literal.9, id=24) + or.21: bits[1] = or(literal.5, literal.9, id=21) + literal.6: bits[1] = literal(value=0, id=6) + assert.20: token = assert(assert.14, or.19, message="State element read after read in same activation.", id=20) + or.25: bits[1] = or(not.24, or.21, id=25) + not.27: bits[1] = not(literal.9, id=27) + not.28: bits[1] = not(literal.6, id=28) + state_0: bits[32] = state_read(state_element=state_0, id=7) + state_1: bits[32] = state_read(state_element=state_1, id=8) + assert.26: token = assert(assert.20, or.25, message="State element written before read in same activation.", id=26) + or.29: bits[1] = or(not.27, not.28, id=29) + not.36: bits[1] = not(literal.9, id=36) + or.31: bits[1] = or(literal.6, literal.9, id=31) + a: bits[32] = identity(state_0, id=16) + b: bits[32] = identity(state_1, id=22) + assert.30: token = assert(assert.26, or.29, message="State element written after write in same activation.", id=30) + or.37: bits[1] = or(not.36, or.21, id=37) + not.39: bits[1] = not(literal.9, id=39) + not.40: bits[1] = not(or.31, id=40) + literal.34: bits[32] = literal(value=1, id=34) + add.23: bits[32] = add(a, b, id=23) + assert.38: token = assert(assert.30, or.37, message="State element written before read in same activation.", id=38) + or.41: bits[1] = or(not.39, not.40, id=41) + add.35: bits[32] = add(a, literal.34, id=35) + __state: (bits[32], bits[32]) = state_read(state_element=__state, id=2) + literal.4: bits[1] = literal(value=0, id=4) + tuple.10: () = tuple(id=10) + or.15: bits[1] = or(literal.3, literal.9, id=15) + next_value.32: () = next_value(param=state_1, value=add.23, predicate=literal.9, id=32) + tuple.33: () = tuple(id=33) + assert.42: token = assert(assert.38, or.41, message="State element written after write in same activation.", id=42) + or.43: bits[1] = or(or.31, literal.9, id=43) + next_value.44: () = next_value(param=state_1, value=add.35, predicate=literal.9, id=44) + tuple.45: () = tuple(id=45) + tuple.46: () = tuple(id=46) +} diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleStatesWriteBeforeRead.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleStatesWriteBeforeRead.ir new file mode 100644 index 0000000000..d04a792224 --- /dev/null +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleStatesWriteBeforeRead.ir @@ -0,0 +1,33 @@ +package test_module + +file_number 0 "test_module.x" + +top proc __test_module__main_0_next<>(__state: (bits[32], bits[32]), state_0: bits[32], state_1: bits[32], init={(0, 1), 0, 1}) { + literal.9: bits[1] = literal(value=1, id=9) + literal.3: bits[1] = literal(value=0, id=3) + not.11: bits[1] = not(literal.9, id=11) + not.12: bits[1] = not(literal.3, id=12) + __token: token = literal(value=token, id=1) + or.13: bits[1] = or(not.11, not.12, id=13) + not.17: bits[1] = not(literal.9, id=17) + literal.5: bits[1] = literal(value=0, id=5) + literal.6: bits[1] = literal(value=0, id=6) + assert.14: token = assert(__token, or.13, message="State element read after read in same activation.", id=14) + or.18: bits[1] = or(not.17, literal.5, id=18) + not.20: bits[1] = not(literal.9, id=20) + not.21: bits[1] = not(literal.6, id=21) + state_0: bits[32] = state_read(state_element=state_0, id=7) + assert.19: token = assert(assert.14, or.18, message="State element written before read in same activation.", id=19) + or.22: bits[1] = or(not.20, not.21, id=22) + state_1: bits[32] = state_read(state_element=state_1, id=8) + a: bits[32] = identity(state_0, id=16) + __state: (bits[32], bits[32]) = state_read(state_element=__state, id=2) + literal.4: bits[1] = literal(value=0, id=4) + tuple.10: () = tuple(id=10) + or.15: bits[1] = or(literal.3, literal.9, id=15) + assert.23: token = assert(assert.19, or.22, message="State element written after write in same activation.", id=23) + or.24: bits[1] = or(literal.6, literal.9, id=24) + next_value.25: () = next_value(param=state_1, value=a, predicate=literal.9, id=25) + tuple.26: () = tuple(id=26) + tuple.27: () = tuple(id=27) +} diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleWrites.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleWrites.ir index 60acb57ff4..e63a5824cc 100644 --- a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleWrites.ir +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessMultipleWrites.ir @@ -2,42 +2,43 @@ package test_module file_number 0 "test_module.x" -top proc __test_module__main_0_next<>(__state: bits[32], init={0}) { - literal.5: bits[1] = literal(value=1, id=5) +top proc __test_module__main_0_next<>(__state: bits[32], state: bits[32], init={0, 0}) { + literal.6: bits[1] = literal(value=1, id=6) literal.3: bits[1] = literal(value=0, id=3) - not.7: bits[1] = not(literal.5, id=7) - not.8: bits[1] = not(literal.3, id=8) + not.8: bits[1] = not(literal.6, id=8) + not.9: bits[1] = not(literal.3, id=9) __token: token = literal(value=token, id=1) - or.9: bits[1] = or(not.7, not.8, id=9) - not.15: bits[1] = not(literal.5, id=15) - or.11: bits[1] = or(literal.3, literal.5, id=11) + or.10: bits[1] = or(not.8, not.9, id=10) + not.16: bits[1] = not(literal.6, id=16) + or.12: bits[1] = or(literal.3, literal.6, id=12) literal.4: bits[1] = literal(value=0, id=4) - assert.10: token = assert(__token, or.9, message="State element read after read in same activation.", id=10) - or.16: bits[1] = or(not.15, or.11, id=16) - not.18: bits[1] = not(literal.5, id=18) - not.19: bits[1] = not(literal.4, id=19) + assert.11: token = assert(__token, or.10, message="State element read after read in same activation.", id=11) + or.17: bits[1] = or(not.16, or.12, id=17) + not.19: bits[1] = not(literal.6, id=19) + not.20: bits[1] = not(literal.4, id=20) + state: bits[32] = state_read(state_element=state, id=5) + assert.18: token = assert(assert.11, or.17, message="State element written before read in same activation.", id=18) + or.21: bits[1] = or(not.19, not.20, id=21) + not.28: bits[1] = not(literal.6, id=28) + or.23: bits[1] = or(literal.4, literal.6, id=23) + identity.13: bits[32] = identity(state, id=13) + literal.14: bits[32] = literal(value=1, id=14) + assert.22: token = assert(assert.18, or.21, message="State element written after write in same activation.", id=22) + or.29: bits[1] = or(not.28, or.12, id=29) + not.31: bits[1] = not(literal.6, id=31) + not.32: bits[1] = not(or.23, id=32) + accum: bits[32] = add(identity.13, literal.14, id=15) + literal.26: bits[32] = literal(value=1, id=26) + assert.30: token = assert(assert.22, or.29, message="State element written before read in same activation.", id=30) + or.33: bits[1] = or(not.31, not.32, id=33) + accum__1: bits[32] = add(accum, literal.26, id=27) __state: bits[32] = state_read(state_element=__state, id=2) - assert.17: token = assert(assert.10, or.16, message="State element written before read in same activation.", id=17) - or.20: bits[1] = or(not.18, not.19, id=20) - not.27: bits[1] = not(literal.5, id=27) - or.22: bits[1] = or(literal.4, literal.5, id=22) - identity.12: bits[32] = identity(__state, id=12) - literal.13: bits[32] = literal(value=1, id=13) - assert.21: token = assert(assert.17, or.20, message="State element written after write in same activation.", id=21) - or.28: bits[1] = or(not.27, or.11, id=28) - not.30: bits[1] = not(literal.5, id=30) - not.31: bits[1] = not(or.22, id=31) - accum: bits[32] = add(identity.12, literal.13, id=14) - literal.25: bits[32] = literal(value=1, id=25) - assert.29: token = assert(assert.21, or.28, message="State element written before read in same activation.", id=29) - or.32: bits[1] = or(not.30, not.31, id=32) - accum__1: bits[32] = add(accum, literal.25, id=26) - tuple.6: () = tuple(id=6) - next_value.23: () = next_value(param=__state, value=accum, predicate=literal.5, id=23) - tuple.24: () = tuple(id=24) - assert.33: token = assert(assert.29, or.32, message="State element written after write in same activation.", id=33) - or.34: bits[1] = or(or.22, literal.5, id=34) - next_value.35: () = next_value(param=__state, value=accum__1, predicate=literal.5, id=35) - tuple.36: () = tuple(id=36) + tuple.7: () = tuple(id=7) + next_value.24: () = next_value(param=state, value=accum, predicate=literal.6, id=24) + tuple.25: () = tuple(id=25) + assert.34: token = assert(assert.30, or.33, message="State element written after write in same activation.", id=34) + or.35: bits[1] = or(or.23, literal.6, id=35) + next_value.36: () = next_value(param=state, value=accum__1, predicate=literal.6, id=36) tuple.37: () = tuple(id=37) + tuple.38: () = tuple(id=38) } diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessReadWithLabeledRead.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessReadWithLabeledRead.ir new file mode 100644 index 0000000000..7b69fcb790 --- /dev/null +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessReadWithLabeledRead.ir @@ -0,0 +1,39 @@ +package test_module + +file_number 0 "test_module.x" + +top proc __test_module__main_0_next<>(__state: bits[32], state: bits[32], init={0, 0}) { + literal.6: bits[1] = literal(value=1, id=6) + literal.3: bits[1] = literal(value=0, id=3) + not.8: bits[1] = not(literal.6, id=8) + not.9: bits[1] = not(literal.3, id=9) + or.12: bits[1] = or(literal.3, literal.6, id=12) + __token: token = literal(value=token, id=1) + or.10: bits[1] = or(not.8, not.9, id=10) + not.14: bits[1] = not(literal.6, id=14) + not.15: bits[1] = not(or.12, id=15) + state: bits[32] = state_read(state_element=state, label="main_read", id=5) + assert.11: token = assert(__token, or.10, message="State element read after read in same activation.", id=11) + or.16: bits[1] = or(not.14, not.15, id=16) + not.23: bits[1] = not(literal.6, id=23) + or.18: bits[1] = or(or.12, literal.6, id=18) + literal.4: bits[1] = literal(value=0, id=4) + x: bits[32] = identity(state, id=19) + literal.20: bits[32] = literal(value=1, id=20) + assert.17: token = assert(assert.11, or.16, message="State element read after read in same activation.", id=17) + or.24: bits[1] = or(not.23, or.18, id=24) + not.26: bits[1] = not(literal.6, id=26) + not.27: bits[1] = not(literal.4, id=27) + add.21: bits[32] = add(x, literal.20, id=21) + curr: bits[32] = identity(state, id=13) + assert.25: token = assert(assert.17, or.24, message="State element written before read in same activation.", id=25) + or.28: bits[1] = or(not.26, not.27, id=28) + y: bits[32] = add(add.21, curr, id=22) + __state: bits[32] = state_read(state_element=__state, id=2) + tuple.7: () = tuple(id=7) + assert.29: token = assert(assert.25, or.28, message="State element written after write in same activation.", id=29) + or.30: bits[1] = or(literal.4, literal.6, id=30) + next_value.31: () = next_value(param=state, value=y, predicate=literal.6, label="main_write", id=31) + tuple.32: () = tuple(id=32) + tuple.33: () = tuple(id=33) +} diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessS32.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessS32.ir index 5419bb02f2..9901901472 100644 --- a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessS32.ir +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessS32.ir @@ -2,30 +2,31 @@ package test_module file_number 0 "test_module.x" -top proc __test_module__Counter_0_next<>(__state: bits[32], init={4294967291}) { - literal.5: bits[1] = literal(value=1, id=5) +top proc __test_module__Counter_0_next<>(__state: bits[32], state: bits[32], init={4294967291, 4294967291}) { + literal.6: bits[1] = literal(value=1, id=6) literal.3: bits[1] = literal(value=0, id=3) - not.7: bits[1] = not(literal.5, id=7) - not.8: bits[1] = not(literal.3, id=8) + not.8: bits[1] = not(literal.6, id=8) + not.9: bits[1] = not(literal.3, id=9) __token: token = literal(value=token, id=1) - or.9: bits[1] = or(not.7, not.8, id=9) - not.15: bits[1] = not(literal.5, id=15) - or.11: bits[1] = or(literal.3, literal.5, id=11) + or.10: bits[1] = or(not.8, not.9, id=10) + not.16: bits[1] = not(literal.6, id=16) + or.12: bits[1] = or(literal.3, literal.6, id=12) literal.4: bits[1] = literal(value=0, id=4) + state: bits[32] = state_read(state_element=state, id=5) + assert.11: token = assert(__token, or.10, message="State element read after read in same activation.", id=11) + or.17: bits[1] = or(not.16, or.12, id=17) + not.19: bits[1] = not(literal.6, id=19) + not.20: bits[1] = not(literal.4, id=20) + current: bits[32] = identity(state, id=13) + literal.14: bits[32] = literal(value=1, id=14) + assert.18: token = assert(assert.11, or.17, message="State element written before read in same activation.", id=18) + or.21: bits[1] = or(not.19, not.20, id=21) + add.15: bits[32] = add(current, literal.14, id=15) __state: bits[32] = state_read(state_element=__state, id=2) - assert.10: token = assert(__token, or.9, message="State element read after read in same activation.", id=10) - or.16: bits[1] = or(not.15, or.11, id=16) - not.18: bits[1] = not(literal.5, id=18) - not.19: bits[1] = not(literal.4, id=19) - current: bits[32] = identity(__state, id=12) - literal.13: bits[32] = literal(value=1, id=13) - assert.17: token = assert(assert.10, or.16, message="State element written before read in same activation.", id=17) - or.20: bits[1] = or(not.18, not.19, id=20) - add.14: bits[32] = add(current, literal.13, id=14) - tuple.6: () = tuple(id=6) - assert.21: token = assert(assert.17, or.20, message="State element written after write in same activation.", id=21) - or.22: bits[1] = or(literal.4, literal.5, id=22) - next_value.23: () = next_value(param=__state, value=add.14, predicate=literal.5, id=23) - tuple.24: () = tuple(id=24) + tuple.7: () = tuple(id=7) + assert.22: token = assert(assert.18, or.21, message="State element written after write in same activation.", id=22) + or.23: bits[1] = or(literal.4, literal.6, id=23) + next_value.24: () = next_value(param=state, value=add.15, predicate=literal.6, id=24) tuple.25: () = tuple(id=25) + tuple.26: () = tuple(id=26) } diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessString.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessString.ir index 8fdb994cf9..972e447631 100644 --- a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessString.ir +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessString.ir @@ -2,29 +2,30 @@ package test_module file_number 0 "test_module.x" -top proc __test_module__String_0_next<>(__state: bits[8][5], init={[104, 101, 108, 108, 111]}) { - literal.5: bits[1] = literal(value=1, id=5) +top proc __test_module__String_0_next<>(__state: bits[8][5], state: bits[8][5], init={[104, 101, 108, 108, 111], [104, 101, 108, 108, 111]}) { + literal.6: bits[1] = literal(value=1, id=6) literal.3: bits[1] = literal(value=0, id=3) - not.7: bits[1] = not(literal.5, id=7) - not.8: bits[1] = not(literal.3, id=8) + not.8: bits[1] = not(literal.6, id=8) + not.9: bits[1] = not(literal.3, id=9) __token: token = literal(value=token, id=1) - or.9: bits[1] = or(not.7, not.8, id=9) - not.14: bits[1] = not(literal.5, id=14) - or.11: bits[1] = or(literal.3, literal.5, id=11) + or.10: bits[1] = or(not.8, not.9, id=10) + not.15: bits[1] = not(literal.6, id=15) + or.12: bits[1] = or(literal.3, literal.6, id=12) literal.4: bits[1] = literal(value=0, id=4) - assert.10: token = assert(__token, or.9, message="State element read after read in same activation.", id=10) - or.15: bits[1] = or(not.14, or.11, id=15) - not.17: bits[1] = not(literal.5, id=17) - not.18: bits[1] = not(literal.4, id=18) + assert.11: token = assert(__token, or.10, message="State element read after read in same activation.", id=11) + or.16: bits[1] = or(not.15, or.12, id=16) + not.18: bits[1] = not(literal.6, id=18) + not.19: bits[1] = not(literal.4, id=19) + state: bits[8][5] = state_read(state_element=state, id=5) + assert.17: token = assert(assert.11, or.16, message="State element written before read in same activation.", id=17) + or.20: bits[1] = or(not.18, not.19, id=20) + literal.14: bits[8][5] = literal(value=[119, 111, 114, 108, 100], id=14) __state: bits[8][5] = state_read(state_element=__state, id=2) - assert.16: token = assert(assert.10, or.15, message="State element written before read in same activation.", id=16) - or.19: bits[1] = or(not.17, not.18, id=19) - literal.13: bits[8][5] = literal(value=[119, 111, 114, 108, 100], id=13) - tuple.6: () = tuple(id=6) - current: bits[8][5] = identity(__state, id=12) - assert.20: token = assert(assert.16, or.19, message="State element written after write in same activation.", id=20) - or.21: bits[1] = or(literal.4, literal.5, id=21) - next_value.22: () = next_value(param=__state, value=literal.13, predicate=literal.5, id=22) - tuple.23: () = tuple(id=23) + tuple.7: () = tuple(id=7) + current: bits[8][5] = identity(state, id=13) + assert.21: token = assert(assert.17, or.20, message="State element written after write in same activation.", id=21) + or.22: bits[1] = or(literal.4, literal.6, id=22) + next_value.23: () = next_value(param=state, value=literal.14, predicate=literal.6, id=23) tuple.24: () = tuple(id=24) + tuple.25: () = tuple(id=25) } diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessStruct.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessStruct.ir index ea99edbd5f..90d9523ac1 100644 --- a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessStruct.ir +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessStruct.ir @@ -2,34 +2,35 @@ package test_module file_number 0 "test_module.x" -top proc __test_module__Struct_0_next<>(__state: (bits[32], bits[32]), init={(0, 0)}) { - literal.5: bits[1] = literal(value=1, id=5) +top proc __test_module__Struct_0_next<>(__state: (bits[32], bits[32]), state: (bits[32], bits[32]), init={(0, 0), (0, 0)}) { + literal.6: bits[1] = literal(value=1, id=6) literal.3: bits[1] = literal(value=0, id=3) - __state: (bits[32], bits[32]) = state_read(state_element=__state, id=2) - not.7: bits[1] = not(literal.5, id=7) - not.8: bits[1] = not(literal.3, id=8) - curr_point: (bits[32], bits[32]) = identity(__state, id=12) + state: (bits[32], bits[32]) = state_read(state_element=state, id=5) + not.8: bits[1] = not(literal.6, id=8) + not.9: bits[1] = not(literal.3, id=9) + curr_point: (bits[32], bits[32]) = identity(state, id=13) __token: token = literal(value=token, id=1) - or.9: bits[1] = or(not.7, not.8, id=9) - not.20: bits[1] = not(literal.5, id=20) - or.11: bits[1] = or(literal.3, literal.5, id=11) + or.10: bits[1] = or(not.8, not.9, id=10) + not.21: bits[1] = not(literal.6, id=21) + or.12: bits[1] = or(literal.3, literal.6, id=12) literal.4: bits[1] = literal(value=0, id=4) - curr_point_x: bits[32] = tuple_index(curr_point, index=0, id=13) - literal.14: bits[32] = literal(value=1, id=14) - curr_point_y: bits[32] = tuple_index(curr_point, index=1, id=16) - literal.17: bits[32] = literal(value=1, id=17) - assert.10: token = assert(__token, or.9, message="State element read after read in same activation.", id=10) - or.21: bits[1] = or(not.20, or.11, id=21) - not.23: bits[1] = not(literal.5, id=23) - not.24: bits[1] = not(literal.4, id=24) - add.15: bits[32] = add(curr_point_x, literal.14, id=15) - add.18: bits[32] = add(curr_point_y, literal.17, id=18) - assert.22: token = assert(assert.10, or.21, message="State element written before read in same activation.", id=22) - or.25: bits[1] = or(not.23, not.24, id=25) - shift: (bits[32], bits[32]) = tuple(add.15, add.18, id=19) - tuple.6: () = tuple(id=6) - assert.26: token = assert(assert.22, or.25, message="State element written after write in same activation.", id=26) - or.27: bits[1] = or(literal.4, literal.5, id=27) - next_value.28: () = next_value(param=__state, value=shift, predicate=literal.5, id=28) - tuple.29: () = tuple(id=29) + curr_point_x: bits[32] = tuple_index(curr_point, index=0, id=14) + literal.15: bits[32] = literal(value=1, id=15) + curr_point_y: bits[32] = tuple_index(curr_point, index=1, id=17) + literal.18: bits[32] = literal(value=1, id=18) + assert.11: token = assert(__token, or.10, message="State element read after read in same activation.", id=11) + or.22: bits[1] = or(not.21, or.12, id=22) + not.24: bits[1] = not(literal.6, id=24) + not.25: bits[1] = not(literal.4, id=25) + add.16: bits[32] = add(curr_point_x, literal.15, id=16) + add.19: bits[32] = add(curr_point_y, literal.18, id=19) + assert.23: token = assert(assert.11, or.22, message="State element written before read in same activation.", id=23) + or.26: bits[1] = or(not.24, not.25, id=26) + shift: (bits[32], bits[32]) = tuple(add.16, add.19, id=20) + __state: (bits[32], bits[32]) = state_read(state_element=__state, id=2) + tuple.7: () = tuple(id=7) + assert.27: token = assert(assert.23, or.26, message="State element written after write in same activation.", id=27) + or.28: bits[1] = or(literal.4, literal.6, id=28) + next_value.29: () = next_value(param=state, value=shift, predicate=literal.6, id=29) + tuple.30: () = tuple(id=30) } diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessU32.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessU32.ir index e03f521888..e69b824374 100644 --- a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessU32.ir +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessU32.ir @@ -2,30 +2,31 @@ package test_module file_number 0 "test_module.x" -top proc __test_module__Counter_0_next<>(__state: bits[32], init={0}) { - literal.5: bits[1] = literal(value=1, id=5) +top proc __test_module__Counter_0_next<>(__state: bits[32], state: bits[32], init={0, 0}) { + literal.6: bits[1] = literal(value=1, id=6) literal.3: bits[1] = literal(value=0, id=3) - not.7: bits[1] = not(literal.5, id=7) - not.8: bits[1] = not(literal.3, id=8) + not.8: bits[1] = not(literal.6, id=8) + not.9: bits[1] = not(literal.3, id=9) __token: token = literal(value=token, id=1) - or.9: bits[1] = or(not.7, not.8, id=9) - not.15: bits[1] = not(literal.5, id=15) - or.11: bits[1] = or(literal.3, literal.5, id=11) + or.10: bits[1] = or(not.8, not.9, id=10) + not.16: bits[1] = not(literal.6, id=16) + or.12: bits[1] = or(literal.3, literal.6, id=12) literal.4: bits[1] = literal(value=0, id=4) + state: bits[32] = state_read(state_element=state, id=5) + assert.11: token = assert(__token, or.10, message="State element read after read in same activation.", id=11) + or.17: bits[1] = or(not.16, or.12, id=17) + not.19: bits[1] = not(literal.6, id=19) + not.20: bits[1] = not(literal.4, id=20) + x: bits[32] = identity(state, id=13) + literal.14: bits[32] = literal(value=1, id=14) + assert.18: token = assert(assert.11, or.17, message="State element written before read in same activation.", id=18) + or.21: bits[1] = or(not.19, not.20, id=21) + y: bits[32] = add(x, literal.14, id=15) __state: bits[32] = state_read(state_element=__state, id=2) - assert.10: token = assert(__token, or.9, message="State element read after read in same activation.", id=10) - or.16: bits[1] = or(not.15, or.11, id=16) - not.18: bits[1] = not(literal.5, id=18) - not.19: bits[1] = not(literal.4, id=19) - x: bits[32] = identity(__state, id=12) - literal.13: bits[32] = literal(value=1, id=13) - assert.17: token = assert(assert.10, or.16, message="State element written before read in same activation.", id=17) - or.20: bits[1] = or(not.18, not.19, id=20) - y: bits[32] = add(x, literal.13, id=14) - tuple.6: () = tuple(id=6) - assert.21: token = assert(assert.17, or.20, message="State element written after write in same activation.", id=21) - or.22: bits[1] = or(literal.4, literal.5, id=22) - next_value.23: () = next_value(param=__state, value=y, predicate=literal.5, id=23) - tuple.24: () = tuple(id=24) + tuple.7: () = tuple(id=7) + assert.22: token = assert(assert.18, or.21, message="State element written after write in same activation.", id=22) + or.23: bits[1] = or(literal.4, literal.6, id=23) + next_value.24: () = next_value(param=state, value=y, predicate=literal.6, id=24) tuple.25: () = tuple(id=25) + tuple.26: () = tuple(id=26) } diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessWriteBeforeRead.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessWriteBeforeRead.ir index 020c9c01e2..e23d70fddc 100644 --- a/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessWriteBeforeRead.ir +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ExplicitStateAccessWriteBeforeRead.ir @@ -2,23 +2,24 @@ package test_module file_number 0 "test_module.x" -top proc __test_module__main_0_next<>(__state: bits[32], init={0}) { - literal.5: bits[1] = literal(value=1, id=5) - not.8: bits[1] = not(literal.5, id=8) +top proc __test_module__main_0_next<>(__state: bits[32], state: bits[32], init={0, 0}) { + literal.6: bits[1] = literal(value=1, id=6) + not.9: bits[1] = not(literal.6, id=9) literal.3: bits[1] = literal(value=0, id=3) literal.4: bits[1] = literal(value=0, id=4) __token: token = literal(value=token, id=1) - or.9: bits[1] = or(not.8, literal.3, id=9) - not.11: bits[1] = not(literal.5, id=11) - not.12: bits[1] = not(literal.4, id=12) - assert.10: token = assert(__token, or.9, message="State element written before read in same activation.", id=10) - or.13: bits[1] = or(not.11, not.12, id=13) + or.10: bits[1] = or(not.9, literal.3, id=10) + not.12: bits[1] = not(literal.6, id=12) + not.13: bits[1] = not(literal.4, id=13) + assert.11: token = assert(__token, or.10, message="State element written before read in same activation.", id=11) + or.14: bits[1] = or(not.12, not.13, id=14) + state: bits[32] = state_read(state_element=state, id=5) + literal.8: bits[32] = literal(value=1, id=8) __state: bits[32] = state_read(state_element=__state, id=2) - literal.7: bits[32] = literal(value=1, id=7) - tuple.6: () = tuple(id=6) - assert.14: token = assert(assert.10, or.13, message="State element written after write in same activation.", id=14) - or.15: bits[1] = or(literal.4, literal.5, id=15) - next_value.16: () = next_value(param=__state, value=literal.7, predicate=literal.5, id=16) - tuple.17: () = tuple(id=17) + tuple.7: () = tuple(id=7) + assert.15: token = assert(assert.11, or.14, message="State element written after write in same activation.", id=15) + or.16: bits[1] = or(literal.4, literal.6, id=16) + next_value.17: () = next_value(param=state, value=literal.8, predicate=literal.6, id=17) tuple.18: () = tuple(id=18) + tuple.19: () = tuple(id=19) } diff --git a/xls/interpreter/serial_proc_runtime_test.cc b/xls/interpreter/serial_proc_runtime_test.cc index 996cb8b15e..2ec4e76950 100644 --- a/xls/interpreter/serial_proc_runtime_test.cc +++ b/xls/interpreter/serial_proc_runtime_test.cc @@ -194,6 +194,7 @@ TEST_F(ExplicitStateRuntimeTest, ExplicitStateAccessMultipleReads) { // Negative test - can we handle explicit state access multiple writes TEST_F(ExplicitStateRuntimeTest, ExplicitStateAccessMultipleWrites) { XLS_ASSERT_OK_AND_ASSIGN(auto interpreter, CreateRuntime(GetTestDataPath())); + EXPECT_THAT( interpreter->Tick(), absl_testing::StatusIs( @@ -205,6 +206,7 @@ TEST_F(ExplicitStateRuntimeTest, ExplicitStateAccessMultipleWrites) { // Negative test - can we handle explicit state access write before read TEST_F(ExplicitStateRuntimeTest, ExplicitStateAccessWriteBeforeRead) { XLS_ASSERT_OK_AND_ASSIGN(auto interpreter, CreateRuntime(GetTestDataPath())); + EXPECT_THAT( interpreter->Tick(), absl_testing::StatusIs( @@ -221,6 +223,51 @@ TEST_F(ExplicitStateRuntimeTest, ExplicitStateAccessMatch) { // Negative test - can we handle explicit state access match multiple writes TEST_F(ExplicitStateRuntimeTest, ExplicitStateAccessMatchMultipleWrites) { XLS_ASSERT_OK_AND_ASSIGN(auto interpreter, CreateRuntime(GetTestDataPath())); + + EXPECT_THAT( + interpreter->Tick(), + absl_testing::StatusIs( + absl::StatusCode::kAborted, + ::testing::HasSubstr( + "State element written after write in same activation."))); +} + +TEST_F(ExplicitStateRuntimeTest, ExplicitStateAccessLabeledReadAndWrite) { + XLS_ASSERT_OK_AND_ASSIGN(auto interpreter, CreateRuntime(GetTestDataPath())); + EXPECT_THAT(interpreter->Tick(), absl_testing::IsOk()); +} + +// Negative test - can we handle explicit state access read with labeled read +TEST_F(ExplicitStateRuntimeTest, ExplicitStateAccessReadWithLabeledRead) { + XLS_ASSERT_OK_AND_ASSIGN(auto interpreter, CreateRuntime(GetTestDataPath())); + + EXPECT_THAT(interpreter->Tick(), + absl_testing::StatusIs( + absl::StatusCode::kAborted, + ::testing::HasSubstr( + "State element read after read in same activation."))); +} + +TEST_F(ExplicitStateRuntimeTest, ExplicitStateAccessMultipleStates) { + XLS_ASSERT_OK_AND_ASSIGN(auto interpreter, CreateRuntime(GetTestDataPath())); + EXPECT_THAT(interpreter->Tick(), absl_testing::IsOk()); +} + +TEST_F(ExplicitStateRuntimeTest, + ExplicitStateAccessMultipleStatesMultipleReads) { + XLS_ASSERT_OK_AND_ASSIGN(auto interpreter, CreateRuntime(GetTestDataPath())); + + EXPECT_THAT(interpreter->Tick(), + absl_testing::StatusIs( + absl::StatusCode::kAborted, + ::testing::HasSubstr( + "State element read after read in same activation."))); +} + +TEST_F(ExplicitStateRuntimeTest, + ExplicitStateAccessMultipleStatesMultipleWrites) { + XLS_ASSERT_OK_AND_ASSIGN(auto interpreter, CreateRuntime(GetTestDataPath())); + EXPECT_THAT( interpreter->Tick(), absl_testing::StatusIs( @@ -229,6 +276,17 @@ TEST_F(ExplicitStateRuntimeTest, ExplicitStateAccessMatchMultipleWrites) { "State element written after write in same activation."))); } +TEST_F(ExplicitStateRuntimeTest, + ExplicitStateAccessMultipleStatesWriteBeforeRead) { + XLS_ASSERT_OK_AND_ASSIGN(auto interpreter, CreateRuntime(GetTestDataPath())); + + EXPECT_THAT( + interpreter->Tick(), + absl_testing::StatusIs( + absl::StatusCode::kAborted, + ::testing::HasSubstr( + "State element written before read in same activation."))); +} // Instantiate and run all the tests in proc_runtime_test_base.cc using // proc interpreters. INSTANTIATE_TEST_SUITE_P( diff --git a/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessLabeledReadAndWrite.ir b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessLabeledReadAndWrite.ir new file mode 100644 index 0000000000..581e4e1839 --- /dev/null +++ b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessLabeledReadAndWrite.ir @@ -0,0 +1,31 @@ +package test_module + +file_number 0 "test_module.x" + +top proc __test_module__main_0_next<>(__state: bits[32], init={0}) { + literal.5: bits[1] = literal(value=1, id=5) + literal.3: bits[1] = literal(value=0, id=3) + not.7: bits[1] = not(literal.5, id=7) + not.8: bits[1] = not(literal.3, id=8) + __token: token = literal(value=token, id=1) + or.9: bits[1] = or(not.7, not.8, id=9) + not.15: bits[1] = not(literal.5, id=15) + or.11: bits[1] = or(literal.3, literal.5, id=11) + literal.4: bits[1] = literal(value=0, id=4) + __state: bits[32] = state_read(state_element=__state, label="main_read", id=2) + assert.10: token = assert(__token, or.9, message="State element read after read in same activation.", id=10) + or.16: bits[1] = or(not.15, or.11, id=16) + not.18: bits[1] = not(literal.5, id=18) + not.19: bits[1] = not(literal.4, id=19) + x: bits[32] = identity(__state, id=12) + literal.13: bits[32] = literal(value=1, id=13) + assert.17: token = assert(assert.10, or.16, message="State element written before read in same activation.", id=17) + or.20: bits[1] = or(not.18, not.19, id=20) + y: bits[32] = add(x, literal.13, id=14) + tuple.6: () = tuple(id=6) + assert.21: token = assert(assert.17, or.20, message="State element written after write in same activation.", id=21) + or.22: bits[1] = or(literal.4, literal.5, id=22) + next_value.23: () = next_value(param=__state, value=y, predicate=literal.5, label="main_write", id=23) + tuple.24: () = tuple(id=24) + tuple.25: () = tuple(id=25) +} diff --git a/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStates.ir b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStates.ir new file mode 100644 index 0000000000..1cf875ee03 --- /dev/null +++ b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStates.ir @@ -0,0 +1,84 @@ +package test_module + +file_number 0 "test_module.x" + +top proc __test_module__main_0_next<>(__state: ((bits[32], bits[32]), (bits[32], bits[32]), bits[32]), state_0: (bits[32], bits[32]), state_1: (bits[32], bits[32]), state_2: bits[32], init={((0, 1), (2, 3), 4), (0, 1), (2, 3), 4}) { + literal.12: bits[1] = literal(value=1, id=12) + literal.3: bits[1] = literal(value=0, id=3) + not.14: bits[1] = not(literal.12, id=14) + not.15: bits[1] = not(literal.3, id=15) + literal.5: bits[1] = literal(value=0, id=5) + __token: token = literal(value=token, id=1) + or.16: bits[1] = or(not.14, not.15, id=16) + not.20: bits[1] = not(literal.12, id=20) + not.21: bits[1] = not(literal.5, id=21) + literal.7: bits[1] = literal(value=0, id=7) + assert.17: token = assert(__token, or.16, message="State element read after read in same activation.", id=17) + or.22: bits[1] = or(not.20, not.21, id=22) + not.26: bits[1] = not(literal.12, id=26) + not.27: bits[1] = not(literal.7, id=27) + assert.23: token = assert(assert.17, or.22, message="State element read after read in same activation.", id=23) + or.28: bits[1] = or(not.26, not.27, id=28) + not.46: bits[1] = not(literal.12, id=46) + or.18: bits[1] = or(literal.3, literal.12, id=18) + literal.4: bits[1] = literal(value=0, id=4) + assert.29: token = assert(assert.23, or.28, message="State element read after read in same activation.", id=29) + or.47: bits[1] = or(not.46, or.18, id=47) + not.49: bits[1] = not(literal.12, id=49) + not.50: bits[1] = not(literal.4, id=50) + state_0: (bits[32], bits[32]) = state_read(state_element=state_0, id=9) + state_1: (bits[32], bits[32]) = state_read(state_element=state_1, id=10) + assert.48: token = assert(assert.29, or.47, message="State element written before read in same activation.", id=48) + or.51: bits[1] = or(not.49, not.50, id=51) + not.56: bits[1] = not(literal.12, id=56) + or.24: bits[1] = or(literal.5, literal.12, id=24) + literal.6: bits[1] = literal(value=0, id=6) + a: (bits[32], bits[32]) = identity(state_0, id=19) + b: (bits[32], bits[32]) = identity(state_1, id=25) + state_2: bits[32] = state_read(state_element=state_2, id=11) + assert.52: token = assert(assert.48, or.51, message="State element written after write in same activation.", id=52) + or.57: bits[1] = or(not.56, or.24, id=57) + not.59: bits[1] = not(literal.12, id=59) + not.60: bits[1] = not(literal.6, id=60) + a_x: bits[32] = tuple_index(a, index=0, id=32) + literal.33: bits[32] = literal(value=1, id=33) + tuple_index.36: bits[32] = tuple_index(b, index=1, id=36) + c: bits[32] = identity(state_2, id=31) + tuple_index.40: bits[32] = tuple_index(b, index=0, id=40) + literal.41: bits[32] = literal(value=1, id=41) + literal.43: bits[32] = literal(value=1, id=43) + assert.58: token = assert(assert.52, or.57, message="State element written before read in same activation.", id=58) + or.61: bits[1] = or(not.59, not.60, id=61) + not.68: bits[1] = not(literal.12, id=68) + or.30: bits[1] = or(literal.7, literal.12, id=30) + literal.8: bits[1] = literal(value=0, id=8) + add.34: bits[32] = add(a_x, literal.33, id=34) + add.37: bits[32] = add(tuple_index.36, c, id=37) + add.42: bits[32] = add(tuple_index.40, literal.41, id=42) + add.44: bits[32] = add(c, literal.43, id=44) + assert.62: token = assert(assert.58, or.61, message="State element written after write in same activation.", id=62) + or.69: bits[1] = or(not.68, or.30, id=69) + not.71: bits[1] = not(literal.12, id=71) + not.72: bits[1] = not(literal.8, id=72) + literal.66: bits[32] = literal(value=2, id=66) + new_a: (bits[32], bits[32]) = tuple(add.34, add.37, id=38) + new_b: (bits[32], bits[32]) = tuple(add.42, add.44, id=45) + assert.70: token = assert(assert.62, or.69, message="State element written before read in same activation.", id=70) + or.73: bits[1] = or(not.71, not.72, id=73) + add.67: bits[32] = add(c, literal.66, id=67) + __state: ((bits[32], bits[32]), (bits[32], bits[32]), bits[32]) = state_read(state_element=__state, id=2) + tuple.13: () = tuple(id=13) + literal.35: bits[32] = literal(value=1, id=35) + literal.39: bits[32] = literal(value=0, id=39) + or.53: bits[1] = or(literal.4, literal.12, id=53) + next_value.54: () = next_value(param=state_0, value=new_a, predicate=literal.12, id=54) + tuple.55: () = tuple(id=55) + or.63: bits[1] = or(literal.6, literal.12, id=63) + next_value.64: () = next_value(param=state_1, value=new_b, predicate=literal.12, id=64) + tuple.65: () = tuple(id=65) + assert.74: token = assert(assert.70, or.73, message="State element written after write in same activation.", id=74) + or.75: bits[1] = or(literal.8, literal.12, id=75) + next_value.76: () = next_value(param=state_2, value=add.67, predicate=literal.12, id=76) + tuple.77: () = tuple(id=77) + tuple.78: () = tuple(id=78) +} diff --git a/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStatesMultipleReads.ir b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStatesMultipleReads.ir new file mode 100644 index 0000000000..3e1a16eeda --- /dev/null +++ b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStatesMultipleReads.ir @@ -0,0 +1,29 @@ +package test_module + +file_number 0 "test_module.x" + +top proc __test_module__main_0_next<>(__state: (bits[32], bits[32]), state_0: bits[32], state_1: bits[32], init={(0, 1), 0, 1}) { + literal.9: bits[1] = literal(value=1, id=9) + literal.5: bits[1] = literal(value=0, id=5) + not.11: bits[1] = not(literal.9, id=11) + not.12: bits[1] = not(literal.5, id=12) + or.15: bits[1] = or(literal.5, literal.9, id=15) + __token: token = literal(value=token, id=1) + or.13: bits[1] = or(not.11, not.12, id=13) + not.17: bits[1] = not(literal.9, id=17) + not.18: bits[1] = not(or.15, id=18) + state_1: bits[32] = state_read(state_element=state_1, id=8) + assert.14: token = assert(__token, or.13, message="State element read after read in same activation.", id=14) + or.19: bits[1] = or(not.17, not.18, id=19) + __state: (bits[32], bits[32]) = state_read(state_element=__state, id=2) + literal.3: bits[1] = literal(value=0, id=3) + literal.4: bits[1] = literal(value=0, id=4) + literal.6: bits[1] = literal(value=0, id=6) + state_0: bits[32] = state_read(state_element=state_0, id=7) + tuple.10: () = tuple(id=10) + b_0: bits[32] = identity(state_1, id=16) + assert.20: token = assert(assert.14, or.19, message="State element read after read in same activation.", id=20) + or.21: bits[1] = or(or.15, literal.9, id=21) + b_1: bits[32] = identity(state_1, id=22) + tuple.23: () = tuple(id=23) +} diff --git a/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStatesMultipleWrites.ir b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStatesMultipleWrites.ir new file mode 100644 index 0000000000..3fae4d5360 --- /dev/null +++ b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStatesMultipleWrites.ir @@ -0,0 +1,52 @@ +package test_module + +file_number 0 "test_module.x" + +top proc __test_module__main_0_next<>(__state: (bits[32], bits[32]), state_0: bits[32], state_1: bits[32], init={(0, 1), 0, 1}) { + literal.9: bits[1] = literal(value=1, id=9) + literal.3: bits[1] = literal(value=0, id=3) + not.11: bits[1] = not(literal.9, id=11) + not.12: bits[1] = not(literal.3, id=12) + literal.5: bits[1] = literal(value=0, id=5) + __token: token = literal(value=token, id=1) + or.13: bits[1] = or(not.11, not.12, id=13) + not.17: bits[1] = not(literal.9, id=17) + not.18: bits[1] = not(literal.5, id=18) + assert.14: token = assert(__token, or.13, message="State element read after read in same activation.", id=14) + or.19: bits[1] = or(not.17, not.18, id=19) + not.24: bits[1] = not(literal.9, id=24) + or.21: bits[1] = or(literal.5, literal.9, id=21) + literal.6: bits[1] = literal(value=0, id=6) + assert.20: token = assert(assert.14, or.19, message="State element read after read in same activation.", id=20) + or.25: bits[1] = or(not.24, or.21, id=25) + not.27: bits[1] = not(literal.9, id=27) + not.28: bits[1] = not(literal.6, id=28) + state_0: bits[32] = state_read(state_element=state_0, id=7) + state_1: bits[32] = state_read(state_element=state_1, id=8) + assert.26: token = assert(assert.20, or.25, message="State element written before read in same activation.", id=26) + or.29: bits[1] = or(not.27, not.28, id=29) + not.36: bits[1] = not(literal.9, id=36) + or.31: bits[1] = or(literal.6, literal.9, id=31) + a: bits[32] = identity(state_0, id=16) + b: bits[32] = identity(state_1, id=22) + assert.30: token = assert(assert.26, or.29, message="State element written after write in same activation.", id=30) + or.37: bits[1] = or(not.36, or.21, id=37) + not.39: bits[1] = not(literal.9, id=39) + not.40: bits[1] = not(or.31, id=40) + literal.34: bits[32] = literal(value=1, id=34) + add.23: bits[32] = add(a, b, id=23) + assert.38: token = assert(assert.30, or.37, message="State element written before read in same activation.", id=38) + or.41: bits[1] = or(not.39, not.40, id=41) + add.35: bits[32] = add(a, literal.34, id=35) + __state: (bits[32], bits[32]) = state_read(state_element=__state, id=2) + literal.4: bits[1] = literal(value=0, id=4) + tuple.10: () = tuple(id=10) + or.15: bits[1] = or(literal.3, literal.9, id=15) + next_value.32: () = next_value(param=state_1, value=add.23, predicate=literal.9, id=32) + tuple.33: () = tuple(id=33) + assert.42: token = assert(assert.38, or.41, message="State element written after write in same activation.", id=42) + or.43: bits[1] = or(or.31, literal.9, id=43) + next_value.44: () = next_value(param=state_1, value=add.35, predicate=literal.9, id=44) + tuple.45: () = tuple(id=45) + tuple.46: () = tuple(id=46) +} diff --git a/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStatesWriteBeforeRead.ir b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStatesWriteBeforeRead.ir new file mode 100644 index 0000000000..d04a792224 --- /dev/null +++ b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStatesWriteBeforeRead.ir @@ -0,0 +1,33 @@ +package test_module + +file_number 0 "test_module.x" + +top proc __test_module__main_0_next<>(__state: (bits[32], bits[32]), state_0: bits[32], state_1: bits[32], init={(0, 1), 0, 1}) { + literal.9: bits[1] = literal(value=1, id=9) + literal.3: bits[1] = literal(value=0, id=3) + not.11: bits[1] = not(literal.9, id=11) + not.12: bits[1] = not(literal.3, id=12) + __token: token = literal(value=token, id=1) + or.13: bits[1] = or(not.11, not.12, id=13) + not.17: bits[1] = not(literal.9, id=17) + literal.5: bits[1] = literal(value=0, id=5) + literal.6: bits[1] = literal(value=0, id=6) + assert.14: token = assert(__token, or.13, message="State element read after read in same activation.", id=14) + or.18: bits[1] = or(not.17, literal.5, id=18) + not.20: bits[1] = not(literal.9, id=20) + not.21: bits[1] = not(literal.6, id=21) + state_0: bits[32] = state_read(state_element=state_0, id=7) + assert.19: token = assert(assert.14, or.18, message="State element written before read in same activation.", id=19) + or.22: bits[1] = or(not.20, not.21, id=22) + state_1: bits[32] = state_read(state_element=state_1, id=8) + a: bits[32] = identity(state_0, id=16) + __state: (bits[32], bits[32]) = state_read(state_element=__state, id=2) + literal.4: bits[1] = literal(value=0, id=4) + tuple.10: () = tuple(id=10) + or.15: bits[1] = or(literal.3, literal.9, id=15) + assert.23: token = assert(assert.19, or.22, message="State element written after write in same activation.", id=23) + or.24: bits[1] = or(literal.6, literal.9, id=24) + next_value.25: () = next_value(param=state_1, value=a, predicate=literal.9, id=25) + tuple.26: () = tuple(id=26) + tuple.27: () = tuple(id=27) +} diff --git a/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessReadWithLabeledRead.ir b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessReadWithLabeledRead.ir new file mode 100644 index 0000000000..14cca82c27 --- /dev/null +++ b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessReadWithLabeledRead.ir @@ -0,0 +1,38 @@ +package test_module + +file_number 0 "test_module.x" + +top proc __test_module__main_0_next<>(__state: bits[32], init={0}) { + literal.5: bits[1] = literal(value=1, id=5) + literal.3: bits[1] = literal(value=0, id=3) + not.7: bits[1] = not(literal.5, id=7) + not.8: bits[1] = not(literal.3, id=8) + or.11: bits[1] = or(literal.3, literal.5, id=11) + __token: token = literal(value=token, id=1) + or.9: bits[1] = or(not.7, not.8, id=9) + not.13: bits[1] = not(literal.5, id=13) + not.14: bits[1] = not(or.11, id=14) + __state: bits[32] = state_read(state_element=__state, label="main_read", id=2) + assert.10: token = assert(__token, or.9, message="State element read after read in same activation.", id=10) + or.15: bits[1] = or(not.13, not.14, id=15) + not.22: bits[1] = not(literal.5, id=22) + or.17: bits[1] = or(or.11, literal.5, id=17) + literal.4: bits[1] = literal(value=0, id=4) + x: bits[32] = identity(__state, id=18) + literal.19: bits[32] = literal(value=1, id=19) + assert.16: token = assert(assert.10, or.15, message="State element read after read in same activation.", id=16) + or.23: bits[1] = or(not.22, or.17, id=23) + not.25: bits[1] = not(literal.5, id=25) + not.26: bits[1] = not(literal.4, id=26) + add.20: bits[32] = add(x, literal.19, id=20) + curr: bits[32] = identity(__state, id=12) + assert.24: token = assert(assert.16, or.23, message="State element written before read in same activation.", id=24) + or.27: bits[1] = or(not.25, not.26, id=27) + y: bits[32] = add(add.20, curr, id=21) + tuple.6: () = tuple(id=6) + assert.28: token = assert(assert.24, or.27, message="State element written after write in same activation.", id=28) + or.29: bits[1] = or(literal.4, literal.5, id=29) + next_value.30: () = next_value(param=__state, value=y, predicate=literal.5, label="main_write", id=30) + tuple.31: () = tuple(id=31) + tuple.32: () = tuple(id=32) +} diff --git a/xls/ir/function.cc b/xls/ir/function.cc index 56784e15be..657093bc0a 100644 --- a/xls/ir/function.cc +++ b/xls/ir/function.cc @@ -329,7 +329,7 @@ absl::Status Function::InternalRebuildSideTables() { // only held in the side table. We can still check for correctness at least. // TODO(allight): We should ideally be able to do this. XLS_RET_CHECK(next_values_.empty()); - XLS_RET_CHECK(next_values_by_state_read_.empty()); + XLS_RET_CHECK(next_values_by_state_element_.empty()); for (Param* p : params_) { XLS_RET_CHECK(p->function_base() == this) diff --git a/xls/ir/function_base.cc b/xls/ir/function_base.cc index 67805781be..f341b4289b 100644 --- a/xls/ir/function_base.cc +++ b/xls/ir/function_base.cc @@ -29,6 +29,7 @@ #include "absl/algorithm/container.h" #include "absl/base/casts.h" +#include "absl/base/no_destructor.h" #include "absl/container/btree_set.h" #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" @@ -245,7 +246,8 @@ void FunctionBase::TakeOwnershipOfNode(std::unique_ptr&& node) { FunctionBase* old_owner = node->function_base(); if (node->Is()) { - old_owner->next_values_by_state_read_.erase(node->As()); + old_owner->next_values_by_state_element_.erase( + node->As()->state_element()); } old_owner->node_iterators_.erase(node.get()); @@ -442,6 +444,34 @@ absl::StatusOr FunctionBase::GetNode( absl::StrFormat("GetNode(%s) failed.", standard_node_name)); } +const absl::btree_set& FunctionBase::next_values( + StateRead* state_read) const { + return next_values(state_read->state_element()); +} + +const absl::btree_set& FunctionBase::next_values( + StateElement* state_element) const { + if (!next_values_by_state_element_.contains(state_element)) { + static const absl::NoDestructor< + absl::btree_set> + kEmptySet; + // This should be pretty rare. Basically this should only happen in the + // short time before the non-updated state element is replaced. Just + // returning what is actually there is nicer than crashing however. Do + // check that this is not just some sort of weird corruption however. + CHECK(absl::c_none_of(nodes(), + [state_element](Node* n) { + return n->Is() && + n->As()->state_element() == + state_element; + })) + << "Invalid side table for next values. Missing " << state_element + << " in " << this; + return *kEmptySet; + } + return next_values_by_state_element_.at(state_element); +} + absl::Status FunctionBase::RemoveNode(Node* node) { XLS_RET_CHECK(node->users().empty()) << node->GetName(); XLS_RET_CHECK(!HasImplicitUse(node)) << node->GetName(); @@ -462,13 +492,12 @@ absl::Status FunctionBase::RemoveNode(Node* node) { params_.end()); } if (node->Is()) { - next_values_by_state_read_.erase(node->As()); + next_values_by_state_element_.erase(node->As()->state_element()); } if (node->Is()) { Next* next = node->As(); - if (next->state_read()->Is()) { // Could've been replaced. - StateRead* state_read = next->state_read()->As(); - next_values_by_state_read_.at(state_read).erase(next); + if (next_values_by_state_element_.contains(next->state_element())) { + next_values_by_state_element_.at(next->state_element()).erase(next); } std::erase(next_values_, next); } @@ -559,13 +588,12 @@ Node* FunctionBase::AddNodeInternal(std::unique_ptr node) { params_.push_back(node->As()); } if (node->Is()) { - next_values_by_state_read_[node->As()]; + next_values_by_state_element_[node->As()->state_element()]; } if (node->Is()) { Next* next = node->As(); - StateRead* state_read = next->state_read()->As(); - next_values_.push_back(node->As()); - next_values_by_state_read_[state_read].insert(next); + next_values_.push_back(next); + next_values_by_state_element_[next->state_element()].insert(next); } Node* ptr = node.get(); node_iterators_[ptr] = nodes_.insert(nodes_.end(), std::move(node)); @@ -683,7 +711,7 @@ absl::Status FunctionBase::RebuildSideTables() { // TODO(allight): The fact that there is so much crap in the function_base // itself is a problem. Having next's and params' in the function base doesn't // make a ton of sense. - // NB Because of above the next-values/next_values_by_state_read_ and params + // NB Because of above the next-values/next_values_by_state_element_ and // lists are updated in proc and function respectively. // NB We assume that node_iterators_ never gets invalidated. XLS_RETURN_IF_ERROR(InternalRebuildSideTables()); diff --git a/xls/ir/function_base.h b/xls/ir/function_base.h index 76f3fc391e..ab19e86fd6 100644 --- a/xls/ir/function_base.h +++ b/xls/ir/function_base.h @@ -26,8 +26,6 @@ #include #include -#include "absl/algorithm/container.h" -#include "absl/base/no_destructor.h" #include "absl/base/optimization.h" #include "absl/container/btree_set.h" #include "absl/container/flat_hash_map.h" @@ -249,26 +247,10 @@ class FunctionBase { absl::Span next_values() const { return next_values_; } const absl::btree_set& next_values( - StateRead* state_read) const { - if (!next_values_by_state_read_.contains(state_read)) { - // This should be pretty rare. Basically this should only happen in the - // short time before the non-updated state element is replaced. Just - // returning what is actually there is nicer than crashing however. Do - // check that this is not just some sort of weird corruption however. - static const absl::NoDestructor< - absl::btree_set> - kEmptySet; - CHECK(absl::c_none_of(nodes(), - [state_read](Node* n) { - return n->Is() && - n->As()->state_read() == state_read; - })) - << "Invalid side table for next values. Missing " << state_read - << " in " << this; - return *kEmptySet; - } - return next_values_by_state_read_.at(state_read); - } + StateRead* state_read) const; + + const absl::btree_set& next_values( + StateElement* state_element) const; // Moves the given param to the given index in the parameter list. absl::Status MoveParamToIndex(Param* param, int64_t index); @@ -497,7 +479,7 @@ class FunctionBase { // together. return !n->Is() && !n->Is(); }); - other.next_values_by_state_read_.clear(); + other.next_values_by_state_element_.clear(); other.next_values_.clear(); } @@ -553,8 +535,9 @@ class FunctionBase { std::vector params_; std::vector next_values_; - absl::flat_hash_map> - next_values_by_state_read_; + absl::flat_hash_map> + next_values_by_state_element_; NameUniquer node_name_uniquer_ = NameUniquer(/*separator=*/"__", GetIrReservedWords()); diff --git a/xls/ir/node.cc b/xls/ir/node.cc index ecb21e8575..f5658077b4 100644 --- a/xls/ir/node.cc +++ b/xls/ir/node.cc @@ -640,8 +640,14 @@ std::string Node::ToStringInternal(bool include_operand_types) const { } case Op::kNext: { const Next* next = As(); - args = {absl::StrFormat("param=%s", next->state_read()->GetName()), - absl::StrFormat("value=%s", next->value()->GetName())}; + if (next->has_state_read_operand()) { + args = {absl::StrFormat("param=%s", next->state_read()->GetName()), + absl::StrFormat("value=%s", next->value()->GetName())}; + } else { + args = { + absl::StrFormat("state_element=%s", next->state_element()->name()), + absl::StrFormat("value=%s", next->value()->GetName())}; + } std::optional predicate = next->predicate(); if (predicate.has_value()) { args.push_back( diff --git a/xls/ir/nodes.cc b/xls/ir/nodes.cc index 763b4bfe03..629c4b4fc2 100755 --- a/xls/ir/nodes.cc +++ b/xls/ir/nodes.cc @@ -988,6 +988,7 @@ Next::Next(const SourceInfo& loc, StateElement* state_element, Node* value, : Node(Op::kNext, function->package()->GetTupleType({}), loc, name, function), state_element_(state_element), + has_state_read_operand_(false), has_predicate_(predicate.has_value()), predicate_operand_index_(1), label_(std::move(label)) { @@ -1002,6 +1003,8 @@ Next::Next(const SourceInfo& loc, Node* state_read, Node* value, std::string_view name, FunctionBase* function) : Node(Op::kNext, function->package()->GetTupleType({}), loc, name, function), + state_element_(state_read->As()->state_element()), + has_state_read_operand_(true), has_predicate_(predicate.has_value()), predicate_operand_index_(2), label_(std::move(label)) { @@ -1466,17 +1469,17 @@ absl::StatusOr StateRead::CloneInNewFunction( absl::StatusOr Next::CloneInNewFunction( absl::Span new_operands, FunctionBase* new_function) const { - if (state_element_ != nullptr) { + if (has_state_read_operand()) { return new_function->MakeNodeWithName( - loc(), state_element_, new_operands[0], - new_operands.size() > 1 ? std::make_optional(new_operands[1]) + loc(), new_operands[0], new_operands[1], + new_operands.size() > 2 ? std::make_optional(new_operands[2]) : std::nullopt, label(), GetNameView()); } // TODO(meheff): Choose an appropriate name for the cloned node. return new_function->MakeNodeWithName( - loc(), new_operands[0], new_operands[1], - new_operands.size() > 2 ? std::make_optional(new_operands[2]) + loc(), state_element(), new_operands[0], + new_operands.size() > 1 ? std::make_optional(new_operands[1]) : std::nullopt, label(), GetNameView()); } diff --git a/xls/ir/nodes.h b/xls/ir/nodes.h index 7cef2f05bd..b29b28550d 100755 --- a/xls/ir/nodes.h +++ b/xls/ir/nodes.h @@ -831,17 +831,12 @@ class Next final : public Node { absl::Span new_operands, FunctionBase* new_function) const final; Node* state_read() const { - CHECK(state_element_ == nullptr) << "StateElement is set"; + CHECK(has_state_read_operand_) + << "Next node does not have a state_read operand"; return operand(0); } - Node* value() const { - if (state_element_ != nullptr) { - return operand(0); - } else { - return operand(1); - } - } + Node* value() const { return operand(has_state_read_operand_ ? 1 : 0); } const std::optional& label() const { return label_; } @@ -885,15 +880,13 @@ class Next final : public Node { bool IsDefinitelyEqualTo(const Node* other) const final; - StateElement* state_element() const { - if (state_element_ != nullptr) { - return state_element_; - } - return state_read()->As()->state_element(); - } + bool has_state_read_operand() const { return has_state_read_operand_; } + + StateElement* state_element() const { return state_element_; } private: - StateElement* state_element_ = nullptr; + StateElement* state_element_; + bool has_state_read_operand_; bool has_predicate_; const int64_t predicate_operand_index_; std::optional label_; diff --git a/xls/ir/proc.cc b/xls/ir/proc.cc index 1d2e41c785..7d689e44c0 100644 --- a/xls/ir/proc.cc +++ b/xls/ir/proc.cc @@ -972,14 +972,20 @@ absl::StatusOr Proc::TransformStateElement( nt.old_next->GetName())); to_replace.push_back({nt.old_next, nxt}); // Identity-ify the old next. - XLS_RETURN_IF_ERROR(nt.old_next->ReplaceOperandNumber( - Next::kValueOperand, nt.old_next->state_read())); + if (nt.old_next->has_state_read_operand()) { + XLS_RETURN_IF_ERROR(nt.old_next->ReplaceOperandNumber( + Next::kValueOperand, nt.old_next->state_read())); + } else { + XLS_RETURN_IF_ERROR( + nt.old_next->ReplaceOperandNumber(/*operand_no=*/0, old_state_read)); + } } for (const auto& [old_n, new_n] : to_replace) { XLS_RETURN_IF_ERROR(old_n->ReplaceUsesWith( new_n, [&](Node* n) { - if (n->Is() && n->As()->state_read() == old_n) { + if (n->Is() && n->As()->has_state_read_operand() && + n->As()->state_read() == old_n) { return false; } return true; @@ -993,7 +999,7 @@ absl::Status Proc::InternalRebuildSideTables() { XLS_RET_CHECK(params_.empty()); // Why is next-values in base but not elements? next_values_.clear(); - next_values_by_state_read_.clear(); + next_values_by_state_element_.clear(); state_reads_.clear(); for (Node* n : nodes()) { if (n->Is()) { @@ -1003,8 +1009,8 @@ absl::Status Proc::InternalRebuildSideTables() { state_reads_[n->As()->state_element()] = n->As(); } else if (n->Is()) { next_values_.push_back(n->As()); - next_values_by_state_read_[n->As()->state_read()->As()] - .insert(n->As()); + next_values_by_state_element_[n->As()->state_element()].insert( + n->As()); } } // TODO(allight): We should make it so we can recover channel/proc-inst things diff --git a/xls/ir/proc_test.cc b/xls/ir/proc_test.cc index 8e382302c5..949421622e 100644 --- a/xls/ir/proc_test.cc +++ b/xls/ir/proc_test.cc @@ -205,6 +205,45 @@ TEST_F(ProcTest, StatelessProc) { EXPECT_EQ(proc->DumpIr(), "proc p() {\n}\n"); } +TEST_F(ProcTest, NextValuesByStateElement) { + auto p = CreatePackage(); + ProcBuilder pb("p", p.get()); + BValue state = pb.StateElement("st", Value(UBits(42, 32))); + BValue add = pb.Add(pb.Literal(UBits(1, 32)), state); + XLS_ASSERT_OK_AND_ASSIGN(Proc * proc, pb.Build({add})); + + StateElement* st_elem = proc->GetStateElement(0); + StateRead* st_read = proc->GetStateRead(st_elem); + + EXPECT_THAT(proc->next_values(st_elem), + ElementsAre(m::Next(m::StateRead("st"), m::Add()))); + EXPECT_THAT(proc->next_values(st_read), + ElementsAre(m::Next(m::StateRead("st"), m::Add()))); + + // Add another next value for the same state element using the StateElement + // constructor. + XLS_ASSERT_OK_AND_ASSIGN( + Node * literal_10, + proc->MakeNode(SourceInfo(), Value(UBits(10, 32)))); + XLS_ASSERT_OK_AND_ASSIGN( + Next * next2, + proc->MakeNode(SourceInfo(), st_elem, literal_10, + /*predicate=*/std::nullopt, /*label=*/std::nullopt)); + + EXPECT_THAT( + proc->next_values(st_elem), + UnorderedElementsAre(m::Next(m::StateRead("st"), m::Add()), next2)); + EXPECT_THAT( + proc->next_values(st_read), + UnorderedElementsAre(m::Next(m::StateRead("st"), m::Add()), next2)); + + XLS_ASSERT_OK(proc->RemoveNode(next2)); + EXPECT_THAT(proc->next_values(st_elem), + ElementsAre(m::Next(m::StateRead("st"), m::Add()))); + EXPECT_THAT(proc->next_values(st_read), + ElementsAre(m::Next(m::StateRead("st"), m::Add()))); +} + TEST_F(ProcTest, RemoveStateThatStillHasUse) { // Don't call CreatePackage which creates a VerifiedPackage because we // intentionally create a malformed proc. diff --git a/xls/ir/verify_node.cc b/xls/ir/verify_node.cc index 7931e869fe..3ec98894a6 100644 --- a/xls/ir/verify_node.cc +++ b/xls/ir/verify_node.cc @@ -978,29 +978,40 @@ class NodeChecker : public DfsVisitor { } absl::Status HandleNext(Next* next) override { - XLS_RETURN_IF_ERROR(ExpectOperandCountRange(next, 2, 3)); - if (!next->state_read()->Is()) { - return absl::InternalError( - absl::StrFormat("Next node %s expects a state read for param; is: %v", - next->GetName(), *next->state_read())); + if (next->has_state_read_operand()) { + XLS_RETURN_IF_ERROR(ExpectOperandCountRange(next, 2, 3)); + if (!next->state_read()->Is()) { + return absl::InternalError(absl::StrFormat( + "Next node %s expects a state read for param; is: %v", + next->GetName(), *next->state_read())); + } + } else { + XLS_RETURN_IF_ERROR(ExpectOperandCountRange(next, 1, 2)); } + if (next->predicate().has_value()) { - XLS_RETURN_IF_ERROR(ExpectOperandHasBitsType(next, /*operand_no=*/2, + XLS_ASSIGN_OR_RETURN(int64_t pred_idx, next->predicate_operand_number()); + XLS_RETURN_IF_ERROR(ExpectOperandHasBitsType(next, pred_idx, /*expected_bit_count=*/1)); } + if (!next->function_base()->HasEffectiveProc()) { return absl::InternalError(absl::StrFormat( - "Next node %s (for param %s) is not in a proc", next->GetName(), - next->state_read()->As()->state_element()->name())); + "Next node %s (for state element %s) is not in a proc", + next->GetName(), next->state_element()->name())); } + Proc* proc = next->function_base()->GetEffectiveProcOrDie(); - XLS_ASSIGN_OR_RETURN( - int64_t index, - proc->GetStateElementIndex( - next->state_read()->As()->state_element())); - XLS_RETURN_IF_ERROR(ExpectOperandHasType(next, /*operand_no=*/0, - proc->GetStateElementType(index))); - return ExpectOperandHasType(next, /*operand_no=*/1, // value is operand 1 + XLS_ASSIGN_OR_RETURN(int64_t index, + proc->GetStateElementIndex(next->state_element())); + + if (next->has_state_read_operand()) { + XLS_RETURN_IF_ERROR(ExpectOperandHasType( + next, /*operand_no=*/0, proc->GetStateElementType(index))); + } + + int64_t value_idx = next->has_state_read_operand() ? 1 : 0; + return ExpectOperandHasType(next, value_idx, proc->GetStateElementType(index)); }