From a4c27737fe29e86c83b3aa7f292fd2670e360bc4 Mon Sep 17 00:00:00 2001 From: Nelson Liang Date: Tue, 4 Aug 2026 12:32:16 -0700 Subject: [PATCH] [Explicit State Access] Support multiple state reads in ir_parser.cc and ir_minimizer_main.cc. Handle IR which creates an implicit state read and contains explicit state read lines. When encountering an explicit state read call, replace the state_element_name entry with the name of the first read, ex `read_1`. Subsequent reads will be named `read_2`, `read_3`, and so on. If there are explicit reads in existing IR files, their first state read will be renamed to the new naming scheme. Since explicit reads also exist within scheduled block IR, add an explicit state_read method to scheduled_builder.cc. PiperOrigin-RevId: 959169498 --- .../pipeline_register_insertion_pass_test.cc | 13 ---- .../state_to_register_io_lowering_pass.cc | 1 + ..._pass_test_SimpleProcWithGlobalChannels.ir | 22 +++--- ...s_test_SimpleProcWithProcScopedChannels.ir | 22 +++--- ...ersion_pass_test_SimpleProcWithoutReset.ir | 20 +++--- ...pass_test_MultiProcWithOneProcScheduled.ir | 4 +- ..._pass_test_SimpleProcWithGlobalChannels.ir | 4 +- ...s_test_SimpleProcWithProcScopedChannels.ir | 4 +- ...o_lowering_test_ProcWithFullBitForToken.ir | 18 ++--- ..._lowering_test_ProcWithNonZeroInitValue.ir | 10 +-- ..._io_lowering_test_SimpleProcWithFullBit.ir | 20 +++--- ...test_SimpleProcWithFullBitAndPredicates.ir | 26 +++---- ...ering_test_SimpleProcWithGlobalChannels.ir | 10 +-- ...est_SimpleProcWithMultipleStateElements.ir | 44 ++++++------ ...g_test_SimpleProcWithProcScopedChannels.ir | 10 +-- xls/dev_tools/ir_minimizer_main.cc | 45 ++++++++---- xls/dev_tools/ir_minimizer_main_test.py | 30 ++++++++ ...tateAccessMultipleBranchingLabeledReads.ir | 8 +-- ...e_test_ExplicitStateAccessMultipleReads.ir | 8 +-- ...tStateAccessMultipleStatesMultipleReads.ir | 8 +-- xls/ir/ir_parser.cc | 72 +++++++++++-------- xls/ir/ir_parser.h | 1 + xls/ir/ir_parser_test.cc | 46 ++++++++++++ xls/ir/proc.cc | 41 ++++++++--- xls/ir/proc.h | 2 + xls/ir/scheduled_builder.cc | 41 +++++++++++ xls/ir/scheduled_builder.h | 11 +-- .../ir_parser_round_trip_test_ParseIIProc.ir | 4 +- ...r_round_trip_test_ParseInstantiatedProc.ir | 16 ++--- ..._test_ParseInstantiatedProcWithZeroArgs.ir | 16 ++--- ...trip_test_ParseInstantiationWithChannel.ir | 4 +- ...t_ParseInstantiationWithNoBypassChannel.ir | 4 +- ...arser_round_trip_test_ParseNewStyleProc.ir | 8 +-- ...st_ParseNewStyleProcNoInterfaceChannels.ir | 8 +-- ...ParseNewStyleProcWithChannelDefinitions.ir | 8 +-- ...arseNewStyleProcWithComplexChannelTypes.ir | 8 +-- ...und_trip_test_ParseProcWithExplicitNext.ir | 8 +-- ...p_test_ParseProcWithPredicatedStateRead.ir | 12 ++-- ...rser_round_trip_test_ParseScheduledProc.ir | 4 +- ..._parser_round_trip_test_ParseSimpleProc.ir | 8 +-- xls/tools/delay_info_main_test.py | 9 +-- xls/tools/eval_proc_main_proc_scoped_test.py | 6 +- 42 files changed, 411 insertions(+), 253 deletions(-) diff --git a/xls/codegen_v_1_5/pipeline_register_insertion_pass_test.cc b/xls/codegen_v_1_5/pipeline_register_insertion_pass_test.cc index 38b3038462..326798e685 100644 --- a/xls/codegen_v_1_5/pipeline_register_insertion_pass_test.cc +++ b/xls/codegen_v_1_5/pipeline_register_insertion_pass_test.cc @@ -434,7 +434,6 @@ TEST_F(PipelineRegisterInsertionPassTest, TestCombinedRegisters) { XLS_ASSERT_OK_AND_ASSIGN(Node * source_acc, source->AppendStateElement( "acc", Value(UBits(0, 32)))); BValue acc = sbb.SourceNode(source_acc); - sbb.AddStateReadToCurrentStage(acc); BValue v0 = sbb.Add(x, acc, SourceInfo(), "v0"); sbb.EndStage(sbb.Literal(UBits(1, 1)), sbb.Literal(UBits(1, 1))); @@ -474,7 +473,6 @@ TEST_F(PipelineRegisterInsertionPassTest, TestRegistersDontCombine) { XLS_ASSERT_OK_AND_ASSIGN(Node * source_acc, source->AppendStateElement( "acc", Value(UBits(0, 32)))); BValue acc = sbb.SourceNode(source_acc); - sbb.AddStateReadToCurrentStage(acc); BValue v0 = sbb.Add(x, acc, SourceInfo(), "v0"); sbb.EndStage(sbb.Literal(UBits(1, 1)), sbb.Literal(UBits(1, 1))); @@ -516,7 +514,6 @@ TEST_F(PipelineRegisterInsertionPassTest, TestCombinedRegistersWithState) { XLS_ASSERT_OK_AND_ASSIGN(Node * source_acc, source->AppendStateElement( "acc", Value(UBits(0, 32)))); BValue acc = sbb.SourceNode(source_acc); - sbb.AddStateReadToCurrentStage(acc); sbb.EndStage(sbb.Literal(UBits(1, 1)), sbb.Literal(UBits(1, 1))); // Stage 1 @@ -573,7 +570,6 @@ TEST_F(PipelineRegisterInsertionPassTest, XLS_ASSERT_OK_AND_ASSIGN(Node * source_acc, source->AppendStateElement( "acc", Value(UBits(0, 32)))); BValue acc = sbb.SourceNode(source_acc); - sbb.AddStateReadToCurrentStage(acc); BValue v0 = sbb.Add(x, acc, SourceInfo(), "v0"); sbb.EndStage(sbb.Literal(UBits(1, 1)), sbb.Literal(UBits(1, 1))); @@ -633,7 +629,6 @@ TEST_F(PipelineRegisterInsertionPassTest, XLS_ASSERT_OK_AND_ASSIGN(Node * source_acc, source->AppendStateElement( "acc", Value(UBits(0, 32)))); BValue acc = sbb.SourceNode(source_acc); - sbb.AddStateReadToCurrentStage(acc); BValue v0 = sbb.Add(x, acc, SourceInfo(), "v0"); sbb.EndStage(sbb.Literal(UBits(1, 1)), sbb.Literal(UBits(1, 1))); @@ -642,7 +637,6 @@ TEST_F(PipelineRegisterInsertionPassTest, XLS_ASSERT_OK_AND_ASSIGN( Node * source_z, source->AppendStateElement("z", Value(UBits(0, 32)))); BValue z = sbb.SourceNode(source_z); - sbb.AddStateReadToCurrentStage(z); sbb.EndStage(sbb.Literal(UBits(1, 1)), sbb.Literal(UBits(1, 1))); // Stage 2 - ends mutex region 1 @@ -700,7 +694,6 @@ TEST_F(PipelineRegisterInsertionPassTest, XLS_ASSERT_OK_AND_ASSIGN(Node * source_acc, source->AppendStateElement( "acc", Value(UBits(0, 32)))); BValue acc = sbb.SourceNode(source_acc); - sbb.AddStateReadToCurrentStage(acc); BValue v0 = sbb.Add(x, acc, SourceInfo(), "v0"); sbb.EndStage(sbb.Literal(UBits(1, 1)), sbb.Literal(UBits(1, 1))); @@ -713,7 +706,6 @@ TEST_F(PipelineRegisterInsertionPassTest, XLS_ASSERT_OK_AND_ASSIGN( Node * source_z, source->AppendStateElement("z", Value(UBits(0, 32)))); BValue z = sbb.SourceNode(source_z); - sbb.AddStateReadToCurrentStage(z); sbb.Next(acc, v0); sbb.EndStage(sbb.Literal(UBits(1, 1)), sbb.Literal(UBits(1, 1))); @@ -767,7 +759,6 @@ TEST_F(PipelineRegisterInsertionPassTest, XLS_ASSERT_OK_AND_ASSIGN(Node * source_acc, source->AppendStateElement( "acc", Value(UBits(0, 32)))); BValue acc = sbb.SourceNode(source_acc); - sbb.AddStateReadToCurrentStage(acc); BValue v0 = sbb.Add(x, acc, SourceInfo(), "v0"); sbb.EndStage(sbb.Literal(UBits(1, 1)), sbb.Literal(UBits(1, 1))); @@ -785,7 +776,6 @@ TEST_F(PipelineRegisterInsertionPassTest, XLS_ASSERT_OK_AND_ASSIGN( Node * source_z, source->AppendStateElement("z", Value(UBits(0, 32)))); BValue z = sbb.SourceNode(source_z); - sbb.AddStateReadToCurrentStage(z); sbb.EndStage(sbb.Literal(UBits(1, 1)), sbb.Literal(UBits(1, 1))); // Stage 4 @@ -838,8 +828,6 @@ TEST_F(PipelineRegisterInsertionPassTest, Node * source_z, source->AppendStateElement("z", Value(UBits(0, 32)))); BValue acc = sbb.SourceNode(source_acc); BValue z = sbb.SourceNode(source_z); - sbb.AddStateReadToCurrentStage(acc); - sbb.AddStateReadToCurrentStage(z); BValue next_acc = sbb.Add(x, acc, SourceInfo(), "next_acc"); sbb.Next(acc, next_acc); sbb.EndStage(sbb.Literal(UBits(1, 1)), sbb.Literal(UBits(1, 1))); @@ -894,7 +882,6 @@ TEST_F(PipelineRegisterInsertionPassTest, XLS_ASSERT_OK_AND_ASSIGN(StateRead * source_read, source->AddStateRead(source_se)); BValue acc = sbb.SourceNode(source_read); - sbb.AddStateReadToCurrentStage(acc); BValue v0 = sbb.Add(x, acc, SourceInfo(), "v0"); sbb.EndStage(sbb.Literal(UBits(1, 1)), sbb.Literal(UBits(1, 1))); diff --git a/xls/codegen_v_1_5/state_to_register_io_lowering_pass.cc b/xls/codegen_v_1_5/state_to_register_io_lowering_pass.cc index 3cdef65ab9..436086d79e 100644 --- a/xls/codegen_v_1_5/state_to_register_io_lowering_pass.cc +++ b/xls/codegen_v_1_5/state_to_register_io_lowering_pass.cc @@ -73,6 +73,7 @@ absl::StatusOr ReplaceNode(Block* block, Node* old_node, Node* new_node, if (old_node->Is()) { XLS_RETURN_IF_ERROR(block->RemoveNodeFromStage(old_node).status()); + XLS_RETURN_IF_ERROR(old_node->function_base()->RemoveNode(old_node)); return false; } if (old_node->IsDead()) { diff --git a/xls/codegen_v_1_5/testdata/scheduled_block_conversion_pass_test_SimpleProcWithGlobalChannels.ir b/xls/codegen_v_1_5/testdata/scheduled_block_conversion_pass_test_SimpleProcWithGlobalChannels.ir index e692c6c2fe..e16ae395db 100644 --- a/xls/codegen_v_1_5/testdata/scheduled_block_conversion_pass_test_SimpleProcWithGlobalChannels.ir +++ b/xls/codegen_v_1_5/testdata/scheduled_block_conversion_pass_test_SimpleProcWithGlobalChannels.ir @@ -9,10 +9,10 @@ top scheduled_block __test__P_0_next(clk: clock, rst: bits[1]) { source proc __test__P_0_next__src(__state: bits[32], init={0}) { } literal.3: bits[1] = literal(value=1, id=3) - stage_inputs_valid_0: bits[1] = literal(value=1, id=19) - stage_outputs_ready_0: bits[1] = literal(value=1, id=20) + stage_inputs_valid_0: bits[1] = literal(value=1, id=20) + stage_outputs_ready_0: bits[1] = literal(value=1, id=21) controlled_stage(stage_inputs_valid_0, stage_outputs_ready_0) { - active_inputs_valid active_inputs_valid_0: bits[1] = literal(value=1, id=21) + active_inputs_valid active_inputs_valid_0: bits[1] = literal(value=1, id=22) after_all.4: token = after_all(id=4) receive.5: (token, bits[32]) = receive(after_all.4, predicate=literal.3, channel=test__a, id=5) tok: token = tuple_index(receive.5, index=0, id=7) @@ -21,17 +21,17 @@ top scheduled_block __test__P_0_next(clk: clock, rst: bits[1]) { tok__1: token = tuple_index(receive.9, index=0, id=11) b_value: bits[32] = tuple_index(receive.9, index=1, id=12) umul.13: bits[32] = umul(a_value, b_value, id=13) - ret stage_outputs_valid_0: bits[1] = and(stage_inputs_valid_0, active_inputs_valid_0, id=22) + ret stage_outputs_valid_0: bits[1] = and(stage_inputs_valid_0, active_inputs_valid_0, id=23) } - stage_inputs_valid_1: bits[1] = literal(value=1, id=23) - stage_outputs_ready_1: bits[1] = literal(value=1, id=24) + stage_inputs_valid_1: bits[1] = literal(value=1, id=24) + stage_outputs_ready_1: bits[1] = literal(value=1, id=25) controlled_stage(stage_inputs_valid_1, stage_outputs_ready_1) { - active_inputs_valid active_inputs_valid_1: bits[1] = literal(value=1, id=25) - __state: bits[32] = state_read(state_element=__state, id=2) - result_value: bits[32] = add(umul.13, __state, id=14) + active_inputs_valid active_inputs_valid_1: bits[1] = literal(value=1, id=26) + __state__1: bits[32] = state_read(state_element=__state, id=2) + result_value: bits[32] = add(umul.13, __state__1, id=14) send.15: token = send(tok__1, result_value, predicate=literal.3, channel=test__result, id=15) next_value.16: () = next_value(state_element=__state, value=result_value, id=16) - ret stage_outputs_valid_1: bits[1] = and(stage_inputs_valid_1, active_inputs_valid_1, id=26) + ret stage_outputs_valid_1: bits[1] = and(stage_inputs_valid_1, active_inputs_valid_1, id=27) } - rst: bits[1] = input_port(name=rst, id=18) + rst: bits[1] = input_port(name=rst, id=19) } diff --git a/xls/codegen_v_1_5/testdata/scheduled_block_conversion_pass_test_SimpleProcWithProcScopedChannels.ir b/xls/codegen_v_1_5/testdata/scheduled_block_conversion_pass_test_SimpleProcWithProcScopedChannels.ir index 4d539c6f46..338c2ab54e 100644 --- a/xls/codegen_v_1_5/testdata/scheduled_block_conversion_pass_test_SimpleProcWithProcScopedChannels.ir +++ b/xls/codegen_v_1_5/testdata/scheduled_block_conversion_pass_test_SimpleProcWithProcScopedChannels.ir @@ -8,10 +8,10 @@ top scheduled_block __test__P_0_next(clk: clock, rst: bits[1]) { chan_interface result(direction=send, kind=streaming, strictness=proven_mutually_exclusive, flow_control=ready_valid, flop_kind=none) } literal.3: bits[1] = literal(value=1, id=3) - stage_inputs_valid_0: bits[1] = literal(value=1, id=20) - stage_outputs_ready_0: bits[1] = literal(value=1, id=21) + stage_inputs_valid_0: bits[1] = literal(value=1, id=21) + stage_outputs_ready_0: bits[1] = literal(value=1, id=22) controlled_stage(stage_inputs_valid_0, stage_outputs_ready_0) { - active_inputs_valid active_inputs_valid_0: bits[1] = literal(value=1, id=22) + active_inputs_valid active_inputs_valid_0: bits[1] = literal(value=1, id=23) after_all.5: token = after_all(id=5) receive.6: (token, bits[32]) = receive(after_all.5, predicate=literal.3, channel=a, id=6) tok: token = tuple_index(receive.6, index=0, id=8) @@ -20,17 +20,17 @@ top scheduled_block __test__P_0_next(clk: clock, rst: bits[1]) { tok__1: token = tuple_index(receive.10, index=0, id=12) b_value: bits[32] = tuple_index(receive.10, index=1, id=13) umul.14: bits[32] = umul(a_value, b_value, id=14) - ret stage_outputs_valid_0: bits[1] = and(stage_inputs_valid_0, active_inputs_valid_0, id=23) + ret stage_outputs_valid_0: bits[1] = and(stage_inputs_valid_0, active_inputs_valid_0, id=24) } - stage_inputs_valid_1: bits[1] = literal(value=1, id=24) - stage_outputs_ready_1: bits[1] = literal(value=1, id=25) + stage_inputs_valid_1: bits[1] = literal(value=1, id=25) + stage_outputs_ready_1: bits[1] = literal(value=1, id=26) controlled_stage(stage_inputs_valid_1, stage_outputs_ready_1) { - active_inputs_valid active_inputs_valid_1: bits[1] = literal(value=1, id=26) - __state: bits[32] = state_read(state_element=__state, id=2) - result_value: bits[32] = add(umul.14, __state, id=15) + active_inputs_valid active_inputs_valid_1: bits[1] = literal(value=1, id=27) + __state__1: bits[32] = state_read(state_element=__state, id=2) + result_value: bits[32] = add(umul.14, __state__1, id=15) send.16: token = send(tok__1, result_value, predicate=literal.3, channel=result, id=16) next_value.17: () = next_value(state_element=__state, value=result_value, id=17) - ret stage_outputs_valid_1: bits[1] = and(stage_inputs_valid_1, active_inputs_valid_1, id=27) + ret stage_outputs_valid_1: bits[1] = and(stage_inputs_valid_1, active_inputs_valid_1, id=28) } - rst: bits[1] = input_port(name=rst, id=19) + rst: bits[1] = input_port(name=rst, id=20) } diff --git a/xls/codegen_v_1_5/testdata/scheduled_block_conversion_pass_test_SimpleProcWithoutReset.ir b/xls/codegen_v_1_5/testdata/scheduled_block_conversion_pass_test_SimpleProcWithoutReset.ir index b13c9ceab9..8b84dad4bc 100644 --- a/xls/codegen_v_1_5/testdata/scheduled_block_conversion_pass_test_SimpleProcWithoutReset.ir +++ b/xls/codegen_v_1_5/testdata/scheduled_block_conversion_pass_test_SimpleProcWithoutReset.ir @@ -7,10 +7,10 @@ top scheduled_block __test__P_0_next(clk: clock) { chan_interface result(direction=send, kind=streaming, strictness=proven_mutually_exclusive, flow_control=ready_valid, flop_kind=none) } literal.3: bits[1] = literal(value=1, id=3) - stage_inputs_valid_0: bits[1] = literal(value=1, id=19) - stage_outputs_ready_0: bits[1] = literal(value=1, id=20) + stage_inputs_valid_0: bits[1] = literal(value=1, id=20) + stage_outputs_ready_0: bits[1] = literal(value=1, id=21) controlled_stage(stage_inputs_valid_0, stage_outputs_ready_0) { - active_inputs_valid active_inputs_valid_0: bits[1] = literal(value=1, id=21) + active_inputs_valid active_inputs_valid_0: bits[1] = literal(value=1, id=22) after_all.5: token = after_all(id=5) receive.6: (token, bits[32]) = receive(after_all.5, predicate=literal.3, channel=a, id=6) tok: token = tuple_index(receive.6, index=0, id=8) @@ -19,16 +19,16 @@ top scheduled_block __test__P_0_next(clk: clock) { tok__1: token = tuple_index(receive.10, index=0, id=12) b_value: bits[32] = tuple_index(receive.10, index=1, id=13) umul.14: bits[32] = umul(a_value, b_value, id=14) - ret stage_outputs_valid_0: bits[1] = and(stage_inputs_valid_0, active_inputs_valid_0, id=22) + ret stage_outputs_valid_0: bits[1] = and(stage_inputs_valid_0, active_inputs_valid_0, id=23) } - stage_inputs_valid_1: bits[1] = literal(value=1, id=23) - stage_outputs_ready_1: bits[1] = literal(value=1, id=24) + stage_inputs_valid_1: bits[1] = literal(value=1, id=24) + stage_outputs_ready_1: bits[1] = literal(value=1, id=25) controlled_stage(stage_inputs_valid_1, stage_outputs_ready_1) { - active_inputs_valid active_inputs_valid_1: bits[1] = literal(value=1, id=25) - __state: bits[32] = state_read(state_element=__state, id=2) - result_value: bits[32] = add(umul.14, __state, id=15) + active_inputs_valid active_inputs_valid_1: bits[1] = literal(value=1, id=26) + __state__1: bits[32] = state_read(state_element=__state, id=2) + result_value: bits[32] = add(umul.14, __state__1, id=15) send.16: token = send(tok__1, result_value, predicate=literal.3, channel=result, id=16) next_value.17: () = next_value(state_element=__state, value=result_value, id=17) - ret stage_outputs_valid_1: bits[1] = and(stage_inputs_valid_1, active_inputs_valid_1, id=26) + ret stage_outputs_valid_1: bits[1] = and(stage_inputs_valid_1, active_inputs_valid_1, id=27) } } diff --git a/xls/codegen_v_1_5/testdata/scheduling_pass_test_MultiProcWithOneProcScheduled.ir b/xls/codegen_v_1_5/testdata/scheduling_pass_test_MultiProcWithOneProcScheduled.ir index af67e04869..69ec2541f5 100644 --- a/xls/codegen_v_1_5/testdata/scheduling_pass_test_MultiProcWithOneProcScheduled.ir +++ b/xls/codegen_v_1_5/testdata/scheduling_pass_test_MultiProcWithOneProcScheduled.ir @@ -17,8 +17,8 @@ top scheduled_proc __test__P_0_next(__state: bits[32], init={0}) { umul.13: bits[32] = umul(a_value, b_value, id=13) } stage { - __state: bits[32] = state_read(state_element=__state, id=2) - result_value: bits[32] = add(umul.13, __state, id=14) + __state__1: bits[32] = state_read(state_element=__state, id=2) + result_value: bits[32] = add(umul.13, __state__1, id=14) send.15: token = send(tok__1, result_value, predicate=literal.3, channel=test__result, id=15) next_value.16: () = next_value(state_element=__state, value=result_value, id=16) } diff --git a/xls/codegen_v_1_5/testdata/scheduling_pass_test_SimpleProcWithGlobalChannels.ir b/xls/codegen_v_1_5/testdata/scheduling_pass_test_SimpleProcWithGlobalChannels.ir index af67e04869..69ec2541f5 100644 --- a/xls/codegen_v_1_5/testdata/scheduling_pass_test_SimpleProcWithGlobalChannels.ir +++ b/xls/codegen_v_1_5/testdata/scheduling_pass_test_SimpleProcWithGlobalChannels.ir @@ -17,8 +17,8 @@ top scheduled_proc __test__P_0_next(__state: bits[32], init={0}) { umul.13: bits[32] = umul(a_value, b_value, id=13) } stage { - __state: bits[32] = state_read(state_element=__state, id=2) - result_value: bits[32] = add(umul.13, __state, id=14) + __state__1: bits[32] = state_read(state_element=__state, id=2) + result_value: bits[32] = add(umul.13, __state__1, id=14) send.15: token = send(tok__1, result_value, predicate=literal.3, channel=test__result, id=15) next_value.16: () = next_value(state_element=__state, value=result_value, id=16) } diff --git a/xls/codegen_v_1_5/testdata/scheduling_pass_test_SimpleProcWithProcScopedChannels.ir b/xls/codegen_v_1_5/testdata/scheduling_pass_test_SimpleProcWithProcScopedChannels.ir index 9c74f9b385..9a2fb6ed76 100644 --- a/xls/codegen_v_1_5/testdata/scheduling_pass_test_SimpleProcWithProcScopedChannels.ir +++ b/xls/codegen_v_1_5/testdata/scheduling_pass_test_SimpleProcWithProcScopedChannels.ir @@ -16,8 +16,8 @@ top scheduled_proc __test__P_0_next RemoveDeadParameters(FunctionBase* f) { if (f->IsProc()) { Proc* p = f->AsProcOrDie(); absl::flat_hash_set dead_state_elements; - absl::flat_hash_set invariant_state_elements( - p->StateElements().begin(), p->StateElements().end()); + absl::flat_hash_set invariant_state_elements; + for (StateElement* se : p->StateElements()) { + if (p->GetStateReadsByStateElement(se).empty()) { + dead_state_elements.insert(se); + } else { + invariant_state_elements.insert(se); + } + } + for (Next* next : p->next_values()) { - if (next->value() != - p->GetStateReadByStateElement(next->state_element())) { - // This state param is not actually invariant. + if (dead_state_elements.contains(next->state_element())) { + continue; + } + absl::Span reads = + p->GetStateReadsByStateElement(next->state_element()); + if (!absl::c_linear_search(reads, next->value())) { invariant_state_elements.erase(next->state_element()); } } + + // 1. Remove next values for all dead and invariant state elements. + std::vector next_values(p->next_values().begin(), + p->next_values().end()); + for (Next* next : next_values) { + if (dead_state_elements.contains(next->state_element()) || + invariant_state_elements.contains(next->state_element())) { + XLS_RETURN_IF_ERROR(p->RemoveNode(next)); + } + } + + // 2. Replace uses of reads for invariant state elements. for (StateElement* invariant : invariant_state_elements) { - // Replace all uses of invariant state elements (i.e.: ones where - // next[i] == param[i]) with a literal of the initial value. Value init_value = invariant->initial_value(); - Node* state_read = p->GetStateReadByStateElement(invariant); - absl::btree_set next_values = - p->next_values(invariant); - for (Next* next : next_values) { - XLS_RETURN_IF_ERROR(p->RemoveNode(next)); + for (StateRead* read : p->GetStateReadsByStateElement(invariant)) { + XLS_RETURN_IF_ERROR( + read->ReplaceUsesWithNew(init_value).status()); } - XLS_RETURN_IF_ERROR( - state_read->ReplaceUsesWithNew(init_value).status()); dead_state_elements.insert(invariant); } + // 3. Remove the state elements themselves. bool changed = false; for (StateElement* dead : dead_state_elements) { XLS_ASSIGN_OR_RETURN(int64_t index, p->GetStateElementIndex(dead)); diff --git a/xls/dev_tools/ir_minimizer_main_test.py b/xls/dev_tools/ir_minimizer_main_test.py index c45adaa8bf..fe573c20ef 100644 --- a/xls/dev_tools/ir_minimizer_main_test.py +++ b/xls/dev_tools/ir_minimizer_main_test.py @@ -732,6 +732,36 @@ def test_new_style_proc(self): encoding='utf-8', ) + def test_proc_multiple_reads(self): + input_ir = """package foo + +top proc foo(x: bits[32], init={42}) { + chan_interface input(direction=receive, kind=streaming, strictness=proven_mutually_exclusive) + chan_interface output(direction=send, kind=streaming, strictness=proven_mutually_exclusive) + tkn: token = literal(value=token, id=1000) + read1: bits[32] = state_read(state_element=x) + read2: bits[32] = state_read(state_element=x) + receive.1: (token, bits[32]) = receive(tkn, channel=input) + tuple_index.2: bits[32] = tuple_index(receive.1, index=1) + add: bits[32] = add(read1, read2) + send.3: token = send(tkn, add, channel=output) + next_value.4: () = next_value(state_element=x, value=tuple_index.2) +} +""" + ir_file = self.create_tempfile(content=input_ir) + test_sh_file = self.create_tempfile() + self._write_sh_script(test_sh_file.full_path, [r'/usr/bin/env']) # = true + # The minimizer should not crash. + subprocess.check_output( + [ + IR_MINIMIZER_MAIN_PATH, + '--test_executable=' + test_sh_file.full_path, + '--can_remove_params', + ir_file.full_path, + ], + encoding='utf-8', + ) + def test_verify_return_code(self): # If the test script never successfully runs, then ir_minimizer_main should # return nonzero. diff --git a/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleBranchingLabeledReads.ir b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleBranchingLabeledReads.ir index b03953f7c9..3e0c8dd724 100644 --- a/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleBranchingLabeledReads.ir +++ b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleBranchingLabeledReads.ir @@ -21,15 +21,15 @@ top proc __test_module__main_0_next<>(__val: bits[32], __switch: bits[1], init={ or.22: bits[1] = or(not.20, not.21, id=22) not.31: bits[1] = not(and.30, id=31) or.26: bits[1] = or(and.6, and.19, id=26) - __val: bits[32] = state_read(state_element=__val, predicate=and.6, label="EvenRead", id=7) - __val__1: bits[32] = state_read(state_element=__val, predicate=and.19, label="OddRead", id=24) + __val__1: bits[32] = state_read(state_element=__val, predicate=and.6, label="EvenRead", id=7) + __val__2: bits[32] = state_read(state_element=__val, predicate=and.19, label="OddRead", id=24) assert.23: token = assert(assert.14, or.22, message="State element read after read in same activation.", id=23) or.32: bits[1] = or(not.31, or.26, id=32) not.34: bits[1] = not(and.30, id=34) not.35: bits[1] = not(and.11, id=35) - even: bits[32] = identity(__val, id=8) + even: bits[32] = identity(__val__1, id=8) literal.9: bits[32] = literal(value=1, id=9) - odd: bits[32] = identity(__val__1, id=25) + odd: bits[32] = identity(__val__2, id=25) literal.27: bits[32] = literal(value=1, id=27) assert.33: token = assert(assert.23, or.32, message="State element written before read in same activation.", id=33) or.36: bits[1] = or(not.34, not.35, id=36) diff --git a/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleReads.ir b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleReads.ir index b795e7659b..b286faaf73 100644 --- a/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleReads.ir +++ b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleReads.ir @@ -6,14 +6,14 @@ top proc __test_module__main_0_next<>(__state: bits[32], init={0}) { literal.2: bits[1] = literal(value=1, id=2) not.6: bits[1] = not(literal.2, id=6) not.7: bits[1] = not(literal.2, id=7) - __state: bits[32] = state_read(state_element=__state, predicate=literal.2, id=4) + __state__1: bits[32] = state_read(state_element=__state, predicate=literal.2, id=4) __token: token = literal(value=token, id=1) or.8: bits[1] = or(not.6, not.7, id=8) - __state__1: bits[32] = state_read(state_element=__state, predicate=literal.2, id=10) + __state__2: bits[32] = state_read(state_element=__state, predicate=literal.2, id=10) tuple.3: () = tuple(id=3) - first: bits[32] = identity(__state, id=5) + first: bits[32] = identity(__state__1, id=5) assert.9: token = assert(__token, or.8, message="State element read after read in same activation.", id=9) - second: bits[32] = identity(__state__1, id=11) + second: bits[32] = identity(__state__2, id=11) or.12: bits[1] = or(literal.2, literal.2, id=12) tuple.13: () = tuple(id=13) } diff --git a/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStatesMultipleReads.ir b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStatesMultipleReads.ir index 71d30c116a..692a7d53cf 100644 --- a/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStatesMultipleReads.ir +++ b/xls/interpreter/testdata/serial_proc_runtime_test_ExplicitStateAccessMultipleStatesMultipleReads.ir @@ -6,14 +6,14 @@ top proc __test_module__main_0_next<>(__state_0: bits[32], __state_1: bits[32], literal.2: bits[1] = literal(value=1, id=2) not.6: bits[1] = not(literal.2, id=6) not.7: bits[1] = not(literal.2, id=7) - __state_1: bits[32] = state_read(state_element=__state_1, predicate=literal.2, id=4) + __state_1__1: bits[32] = state_read(state_element=__state_1, predicate=literal.2, id=4) __token: token = literal(value=token, id=1) or.8: bits[1] = or(not.6, not.7, id=8) - __state_1__1: bits[32] = state_read(state_element=__state_1, predicate=literal.2, id=10) + __state_1__2: bits[32] = state_read(state_element=__state_1, predicate=literal.2, id=10) tuple.3: () = tuple(id=3) - b_0: bits[32] = identity(__state_1, id=5) + b_0: bits[32] = identity(__state_1__1, id=5) assert.9: token = assert(__token, or.8, message="State element read after read in same activation.", id=9) - b_1: bits[32] = identity(__state_1__1, id=11) + b_1: bits[32] = identity(__state_1__2, id=11) or.12: bits[1] = or(literal.2, literal.2, id=12) tuple.13: () = tuple(id=13) } diff --git a/xls/ir/ir_parser.cc b/xls/ir/ir_parser.cc index 49df0a8278..3f4605d6b7 100644 --- a/xls/ir/ir_parser.cc +++ b/xls/ir/ir_parser.cc @@ -829,27 +829,50 @@ absl::StatusOr Parser::ParseNode( break; } case Op::kStateRead: { - IdentifierString* state_name = + IdentifierString* state_element_name = arg_parser.AddKeywordArg("state_element"); std::optional* predicate = arg_parser.AddOptionalKeywordArg("predicate"); std::optional* label = arg_parser.AddOptionalKeywordArg("label"); XLS_ASSIGN_OR_RETURN(operands, arg_parser.Run(/*arity=*/0)); - auto it = name_to_value->find(state_name->value); - if (it == name_to_value->end()) { - return absl::InvalidArgumentError( - absl::StrFormat("Referred to state name that hadn't yet been " - "defined: %s @ %s", - state_name->value, op_token.pos().ToHumanString())); + XLS_ASSIGN_OR_RETURN( + Proc * proc, GetEffectiveProcOrError( + fb, "state_read operations only supported in procs", + op_token.pos())); + std::optional state_element = + proc->MaybeGetStateElementByName(state_element_name->value); + if (!state_element.has_value()) { + return absl::InvalidArgumentError(absl::StrFormat( + "Referred to state_element name that hadn't yet been " + "defined: %s @ %s", + state_element_name->value, op_token.pos().ToHumanString())); } - bvalue = it->second; - if (predicate->has_value()) { - XLS_RETURN_IF_ERROR( - bvalue.node()->As()->SetPredicate((*predicate)->node())); + + // If an implicit state read already exists, delete it. + auto it = name_to_value->find(state_element_name->value); + if (it != name_to_value->end()) { + Node* old_read = it->second.node(); + name_to_value->erase(it); + XLS_RETURN_IF_ERROR(old_read->function_base()->RemoveNode(old_read)); } - if (label->has_value()) { - bvalue.node()->As()->set_label(label->value().value); + + if (auto* pb = dynamic_cast(fb)) { + bvalue = pb->StateRead(BStateElement(*state_element, pb), *predicate, + label->has_value() + ? std::make_optional(label->value().value) + : std::nullopt, + *loc); + } else if (auto* sbb = dynamic_cast(fb)) { + bvalue = sbb->StateRead(BStateElement(*state_element), *predicate, + label->has_value() + ? std::make_optional(label->value().value) + : std::nullopt, + *loc); + } + + if (!node_name.empty()) { + bvalue.SetName(node_name); } break; } @@ -1934,16 +1957,13 @@ absl::StatusOr Parser::ParseBody( XLS_ASSIGN_OR_RETURN( Proc * source_proc, ParseProc(package, /*outer_attributes=*/{}, &source)); - for (StateElement* element : source_proc->StateElements()) { - absl::Span reads = - source_proc->GetStateReadsByStateElement(element); - // TODO: (nelsonliang) Make this work for multiple reads of the same - // state element. This will require populating `name_to_value` with - // entries for each `StateRead` node (keyed by node name) rather than - // one entry per state element (keyed by state element name). - XLS_RET_CHECK_EQ(reads.size(), 1); - name_to_value->emplace(element->name(), - bb->SourceNode(reads.front())); + // TODO: Clean this up once we require explicit StateRead + // nodes, since they'll added to name_to_value when the IR is parsed. + for (Node* node : source_proc->nodes()) { + if (node->Is()) { + StateRead* read = node->As(); + name_to_value->emplace(read->GetName(), bb->SourceNode(read)); + } } } else { return absl::InvalidArgumentError(absl::StrFormat( @@ -3545,11 +3565,7 @@ absl::Status Parser::ParseControlledStage( } XLS_ASSIGN_OR_RETURN(BValue result, ParseNode(builder, name_to_value)); (*name_to_value)[result.node()->GetName()] = result; - if (result.node()->Is()) { - // State reads are not created the way normal nodes are, so we need to - // force this. - builder->AddStateReadToCurrentStage(result); - } + if (is_active_inputs_valid) { if (active_inputs_valid.has_value()) { return absl::InvalidArgumentError(absl::StrFormat( diff --git a/xls/ir/ir_parser.h b/xls/ir/ir_parser.h index 8416ec7f2c..109973efdc 100644 --- a/xls/ir/ir_parser.h +++ b/xls/ir/ir_parser.h @@ -33,6 +33,7 @@ #include #include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/str_format.h" diff --git a/xls/ir/ir_parser_test.cc b/xls/ir/ir_parser_test.cc index 0da72e07b4..bbf3b47efc 100644 --- a/xls/ir/ir_parser_test.cc +++ b/xls/ir/ir_parser_test.cc @@ -176,6 +176,30 @@ TEST(IrParserTest, ParseSingleEmptyPackageNamedKeywords) { } } +TEST(IrParserTest, ProcWithMultipleReadsOfSameStateElement) { + std::string program = R"( +package test_module + +proc foo(__state: bits[32], __cond: bits[1], init={0, 1}) { + cond: bits[1] = state_read(state_element=__cond) + not_cond: bits[1] = not(cond) + __state_1: bits[32] = state_read(state_element=__state, predicate=cond) + __state_2: bits[32] = state_read(state_element=__state, predicate=not_cond) + next_value.1: () = next_value(state_element=__state, value=__state_1, predicate=cond) + next_value.2: () = next_value(state_element=__state, value=__state_2, predicate=not_cond) + next_value.3: () = next_value(state_element=__cond, value=not_cond) +} + +)"; + XLS_ASSERT_OK_AND_ASSIGN(auto package, Parser::ParsePackage(program)); + XLS_ASSERT_OK_AND_ASSIGN(Proc * proc, package->GetProc("foo")); + EXPECT_EQ(proc->GetStateElementCount(), 2); + XLS_ASSERT_OK_AND_ASSIGN(StateElement * state, + proc->GetStateElementByName("__state")); + absl::Span reads = proc->GetStateReadsByStateElement(state); + EXPECT_EQ(reads.size(), 2); +} + TEST(IrParserTest, ParseSingleFunctionPackage) { std::string input = R"(package SingleFunctionPackage @@ -1232,6 +1256,28 @@ scheduled_block b() { EXPECT_EQ(block->stages().size(), 0); } +TEST(IrParserTest, ScheduledBlockWithMultipleStateReads) { + const std::string input = R"(package test +scheduled_block b() { + source proc foo(__state: bits[32], init={0}) { + } + iv0: bits[1] = literal(value=1, id=1) + or0: bits[1] = literal(value=1, id=2) + controlled_stage(iv0, or0) { + active_inputs_valid aiv0: bits[1] = literal(value=1, id=3) + __state_1: bits[32] = state_read(state_element=__state, id=4) + __state_2: bits[32] = state_read(state_element=__state, id=5) + sum: bits[32] = add(__state_1, __state_2, id=6) + ret ov0: bits[1] = identity(aiv0, id=7) + } +} +)"; + XLS_ASSERT_OK_AND_ASSIGN(std::unique_ptr pkg, + Parser::ParsePackage(input)); + XLS_ASSERT_OK_AND_ASSIGN(Block * block, pkg->GetBlock("b")); + EXPECT_TRUE(block->IsScheduled()); +} + TEST(IrParserTest, ScheduledBlockWithEmptyStage) { const std::string input = R"(package test scheduled_block b() { diff --git a/xls/ir/proc.cc b/xls/ir/proc.cc index c18cd5324d..7194dc368f 100644 --- a/xls/ir/proc.cc +++ b/xls/ir/proc.cc @@ -214,18 +214,19 @@ absl::Status Proc::RemoveStateElement(int64_t index) { StateElement* old_state_element = GetStateElement(index); auto old_state_read_it = state_reads_.find(old_state_element); - XLS_RET_CHECK(old_state_read_it != state_reads_.end()); - for (StateRead* read : old_state_read_it->second) { - if (!read->users().empty()) { - return absl::InvalidArgumentError( - absl::StrFormat("Cannot remove state element %d of proc %s, existing " - "state read %s has uses", - index, name(), read->GetNameView())); + if (old_state_read_it != state_reads_.end()) { + for (StateRead* read : old_state_read_it->second) { + if (!read->users().empty()) { + return absl::InvalidArgumentError(absl::StrFormat( + "Cannot remove state element %d of proc %s, existing " + "state read %s has uses", + index, name(), read->GetNameView())); + } + XLS_RETURN_IF_ERROR(FunctionBase::RemoveNode(read)); } - XLS_RETURN_IF_ERROR(RemoveNode(read)); + // TODO(allight): This should ideally not need to be done manually. + state_reads_.erase(old_state_read_it); } - // TODO(allight): This should ideally not need to be done manually. - state_reads_.erase(old_state_read_it); state_elements_.erase(old_state_element->name()); state_vec_.erase(state_vec_.begin() + index); @@ -238,7 +239,7 @@ absl::Status Proc::RemoveAllStateElements() { for (const auto& [elem, reads] : state_reads_) { for (StateRead* read : reads) { if (read != nullptr) { - XLS_RETURN_IF_ERROR(RemoveNode(read)) + XLS_RETURN_IF_ERROR(FunctionBase::RemoveNode(read)) << "Cannot remove " << elem->ToString() << " of proc " << name() << " because read '" << read->ToString() << "' could not be removed."; @@ -1094,4 +1095,22 @@ void Proc::MoveNonLogicFrom(Proc& other) { channel_vec_ = std::move(other.channel_vec_); } +absl::Status Proc::RemoveNode(Node* n) { + if (n->Is()) { + StateRead* read = n->As(); + auto it = state_reads_.find(read->state_element()); + if (it != state_reads_.end()) { + std::vector& reads = it->second; + auto read_it = std::find(reads.begin(), reads.end(), read); + if (read_it != reads.end()) { + reads.erase(read_it); + } + if (reads.empty()) { + state_reads_.erase(it); + } + } + } + return FunctionBase::RemoveNode(n); +} + } // namespace xls diff --git a/xls/ir/proc.h b/xls/ir/proc.h index c47a25b77b..33036c1d8d 100644 --- a/xls/ir/proc.h +++ b/xls/ir/proc.h @@ -270,6 +270,8 @@ class Proc : public FunctionBase { bool HasImplicitUse(Node* node) const override; + absl::Status RemoveNode(Node* n) override; + // Creates a clone of the proc with the new name `new_name`. Proc is // owned by `target_package`. `channel_remapping` dictates how to map channel // names to new channel names in the cloned version; if a key is unavailable diff --git a/xls/ir/scheduled_builder.cc b/xls/ir/scheduled_builder.cc index 7659f8e2f7..fb79e4232b 100644 --- a/xls/ir/scheduled_builder.cc +++ b/xls/ir/scheduled_builder.cc @@ -15,6 +15,8 @@ #include "xls/ir/scheduled_builder.h" #include +#include +#include #include #include "absl/algorithm/container.h" @@ -35,6 +37,7 @@ #include "xls/ir/nodes.h" #include "xls/ir/package.h" #include "xls/ir/proc.h" +#include "xls/ir/source_location.h" #include "xls/ir/verifier.h" namespace xls { @@ -231,4 +234,42 @@ void ScheduledBlockBuilder::SetSourceReturnValue(Node* return_value) { source_fn->set_return_type(return_value->GetType()); } +BValue ScheduledBlockBuilder::StateRead(BStateElement state_element, + std::optional predicate, + std::optional label, + const SourceInfo& loc) { + if (ErrorPending()) { + return BValue(); + } + if (!state_element.valid()) { + return BValue(); + } + ScheduledBlock* sb = block(); + if (sb->source() == nullptr || !sb->source()->IsProc()) { + return SetError("Block has no proc source for StateRead", loc); + } + Proc* proc = absl::down_cast(sb->source()); + absl::StatusOr se_or_status = + proc->GetStateElementByName(state_element.state_element()->name()); + if (!se_or_status.ok() || + se_or_status.value() != state_element.state_element()) { + return SetError( + absl::StrFormat("State element %s does not belong to the source proc", + state_element.state_element()->name()), + loc); + } + absl::StatusOr state_read = + function()->MakeNodeWithName( + loc, state_element.state_element(), + predicate.has_value() ? std::make_optional(predicate->node()) + : std::nullopt, + label, state_element.state_element()->name()); + if (!state_read.ok()) { + return SetError(absl::StrFormat("Unable to add state read: %s", + state_read.status().message()), + loc); + } + return CreateBValue(*state_read, loc); +} + } // namespace xls diff --git a/xls/ir/scheduled_builder.h b/xls/ir/scheduled_builder.h index 749c2641aa..ffc159f31d 100644 --- a/xls/ir/scheduled_builder.h +++ b/xls/ir/scheduled_builder.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,7 @@ #include "xls/ir/function_builder.h" #include "xls/ir/package.h" #include "xls/ir/proc.h" +#include "xls/ir/source_location.h" namespace xls { @@ -175,11 +177,10 @@ class ScheduledBlockBuilder : public BlockBuilder { // avoid forward referencing in IR text. void SetSourceReturnValue(Node* return_value); - // Indicates that the given state read should be considered part of the - // current stage. State reads are created stageless by default. - void AddStateReadToCurrentStage(BValue state_read) { - current_stage_nodes_.push_back(state_read.node()); - } + BValue StateRead(BStateElement state_element, + std::optional predicate = std::nullopt, + std::optional label = std::nullopt, + const SourceInfo& loc = SourceInfo()); protected: void OnNodeAdded(Node* node) override; diff --git a/xls/ir/testdata/ir_parser_round_trip_test_ParseIIProc.ir b/xls/ir/testdata/ir_parser_round_trip_test_ParseIIProc.ir index f6e67655d5..bba9c48ce3 100644 --- a/xls/ir/testdata/ir_parser_round_trip_test_ParseIIProc.ir +++ b/xls/ir/testdata/ir_parser_round_trip_test_ParseIIProc.ir @@ -2,6 +2,6 @@ package test #[initiation_interval(12)] top proc example(tkn: token, init={token}) { - tkn: token = state_read(state_element=tkn, id=2) - next_value.3: () = next_value(state_element=tkn, value=tkn, id=3) + tkn__1: token = state_read(state_element=tkn, id=2) + next_value.3: () = next_value(state_element=tkn, value=tkn__1, id=3) } diff --git a/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiatedProc.ir b/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiatedProc.ir index 5cf051db14..230411e888 100644 --- a/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiatedProc.ir +++ b/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiatedProc.ir @@ -3,14 +3,14 @@ package test proc my_proc(my_token: token, my_state: bits[32], init={token, 42}) { chan_interface in_ch(direction=receive, kind=single_value, strictness=proven_mutually_exclusive, flow_control=none, flop_kind=none) chan_interface out_ch(direction=send, kind=streaming, flow_control=ready_valid, flop_kind=skid) - my_token: token = state_read(state_element=my_token, id=9) - my_state: bits[32] = state_read(state_element=my_state, id=10) - send.1: token = send(my_token, my_state, channel=out_ch, id=1) + my_token__1: token = state_read(state_element=my_token, id=9) + my_state__1: bits[32] = state_read(state_element=my_state, id=10) + send.1: token = send(my_token__1, my_state__1, channel=out_ch, id=1) literal.2: bits[1] = literal(value=1, id=2) receive.3: (token, bits[32]) = receive(send.1, predicate=literal.2, channel=in_ch, id=3) tuple_index.4: token = tuple_index(receive.3, index=0, id=4) next_value.15: () = next_value(state_element=my_token, value=tuple_index.4, id=15) - next_value.16: () = next_value(state_element=my_state, value=my_state, id=16) + next_value.16: () = next_value(state_element=my_state, value=my_state__1, id=16) } proc other_proc<>(my_token: token, my_state: bits[32], init={token, 42}) { @@ -21,8 +21,8 @@ proc other_proc<>(my_token: token, my_state: bits[32], init={token, 42}) { chan_interface ch_b(direction=send, kind=streaming, flow_control=ready_valid, flop_kind=none) chan_interface ch_b(direction=receive, kind=streaming, flow_control=ready_valid, flop_kind=skid) proc_instantiation foo(ch_a, ch_b, proc=my_proc) - my_token: token = state_read(state_element=my_token, id=11) - my_state: bits[32] = state_read(state_element=my_state, id=12) - next_value.19: () = next_value(state_element=my_token, value=my_token, id=19) - next_value.20: () = next_value(state_element=my_state, value=my_state, id=20) + my_token__1: token = state_read(state_element=my_token, id=11) + my_state__1: bits[32] = state_read(state_element=my_state, id=12) + next_value.19: () = next_value(state_element=my_token, value=my_token__1, id=19) + next_value.20: () = next_value(state_element=my_state, value=my_state__1, id=20) } diff --git a/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiatedProcWithZeroArgs.ir b/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiatedProcWithZeroArgs.ir index 877d4fab9f..0a6a8751c9 100644 --- a/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiatedProcWithZeroArgs.ir +++ b/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiatedProcWithZeroArgs.ir @@ -1,16 +1,16 @@ package test proc my_proc<>(my_token: token, my_state: bits[32], init={token, 42}) { - my_token: token = state_read(state_element=my_token, id=5) - my_state: bits[32] = state_read(state_element=my_state, id=6) - next_value.7: () = next_value(state_element=my_token, value=my_token, id=7) - next_value.8: () = next_value(state_element=my_state, value=my_state, id=8) + my_token__1: token = state_read(state_element=my_token, id=5) + my_state__1: bits[32] = state_read(state_element=my_state, id=6) + next_value.7: () = next_value(state_element=my_token, value=my_token__1, id=7) + next_value.8: () = next_value(state_element=my_state, value=my_state__1, id=8) } proc other_proc<>(my_token: token, my_state: bits[32], init={token, 42}) { proc_instantiation foo(proc=my_proc) - my_token: token = state_read(state_element=my_token, id=9) - my_state: bits[32] = state_read(state_element=my_state, id=10) - next_value.11: () = next_value(state_element=my_token, value=my_token, id=11) - next_value.12: () = next_value(state_element=my_state, value=my_state, id=12) + my_token__1: token = state_read(state_element=my_token, id=9) + my_state__1: bits[32] = state_read(state_element=my_state, id=10) + next_value.11: () = next_value(state_element=my_token, value=my_token__1, id=11) + next_value.12: () = next_value(state_element=my_state, value=my_state__1, id=12) } diff --git a/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiationWithChannel.ir b/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiationWithChannel.ir index 91f1857427..27e8c856af 100644 --- a/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiationWithChannel.ir +++ b/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiationWithChannel.ir @@ -3,8 +3,8 @@ package test chan foo(bits[32], id=42, kind=streaming, ops=send_receive, flow_control=none, strictness=proven_mutually_exclusive, fifo_depth=0, bypass=true, register_push_outputs=false, register_pop_outputs=false) proc placeholder_channel_user(tok: token, init={token}) { - tok: token = state_read(state_element=tok, id=13) - recv_out: (token, bits[32]) = receive(tok, channel=foo, id=1) + tok__1: token = state_read(state_element=tok, id=13) + recv_out: (token, bits[32]) = receive(tok__1, channel=foo, id=1) recv_tok: token = tuple_index(recv_out, index=0, id=2) recv_data: bits[32] = tuple_index(recv_out, index=1, id=3) send_out: token = send(recv_tok, recv_data, channel=foo, id=4) diff --git a/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiationWithNoBypassChannel.ir b/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiationWithNoBypassChannel.ir index d16e2b7753..1f0c515b19 100644 --- a/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiationWithNoBypassChannel.ir +++ b/xls/ir/testdata/ir_parser_round_trip_test_ParseInstantiationWithNoBypassChannel.ir @@ -3,8 +3,8 @@ package test chan foo(bits[32], id=42, kind=streaming, ops=send_receive, flow_control=none, strictness=proven_mutually_exclusive, fifo_depth=1, bypass=false, register_push_outputs=true, register_pop_outputs=true) proc placeholder_channel_user(tok: token, init={token}) { - tok: token = state_read(state_element=tok, id=13) - recv_out: (token, bits[32]) = receive(tok, channel=foo, id=1) + tok__1: token = state_read(state_element=tok, id=13) + recv_out: (token, bits[32]) = receive(tok__1, channel=foo, id=1) recv_tok: token = tuple_index(recv_out, index=0, id=2) recv_data: bits[32] = tuple_index(recv_out, index=1, id=3) send_out: token = send(recv_tok, recv_data, channel=foo, id=4) diff --git a/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProc.ir b/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProc.ir index 10ff27e000..4d118f27a8 100644 --- a/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProc.ir +++ b/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProc.ir @@ -3,12 +3,12 @@ package test proc my_proc(my_token: token, my_state: bits[32], init={token, 42}) { chan_interface in_ch(direction=receive, kind=streaming, strictness=proven_mutually_exclusive, flow_control=none, flop_kind=none) chan_interface out_ch(direction=send, kind=streaming, flow_control=ready_valid, flop_kind=skid) - my_token: token = state_read(state_element=my_token, id=7) - my_state: bits[32] = state_read(state_element=my_state, id=8) - send.1: token = send(my_token, my_state, channel=out_ch, id=1) + my_token__1: token = state_read(state_element=my_token, id=7) + my_state__1: bits[32] = state_read(state_element=my_state, id=8) + send.1: token = send(my_token__1, my_state__1, channel=out_ch, id=1) literal.2: bits[1] = literal(value=1, id=2) receive.3: (token, bits[32]) = receive(send.1, predicate=literal.2, channel=in_ch, id=3) tuple_index.4: token = tuple_index(receive.3, index=0, id=4) next_value.13: () = next_value(state_element=my_token, value=tuple_index.4, id=13) - next_value.14: () = next_value(state_element=my_state, value=my_state, id=14) + next_value.14: () = next_value(state_element=my_state, value=my_state__1, id=14) } diff --git a/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProcNoInterfaceChannels.ir b/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProcNoInterfaceChannels.ir index 73f77436f2..2efcf7d0c4 100644 --- a/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProcNoInterfaceChannels.ir +++ b/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProcNoInterfaceChannels.ir @@ -1,8 +1,8 @@ package test proc my_proc<>(my_token: token, my_state: bits[32], init={token, 42}) { - my_token: token = state_read(state_element=my_token, id=3) - my_state: bits[32] = state_read(state_element=my_state, id=4) - next_value.5: () = next_value(state_element=my_token, value=my_token, id=5) - next_value.6: () = next_value(state_element=my_state, value=my_state, id=6) + my_token__1: token = state_read(state_element=my_token, id=3) + my_state__1: bits[32] = state_read(state_element=my_state, id=4) + next_value.5: () = next_value(state_element=my_token, value=my_token__1, id=5) + next_value.6: () = next_value(state_element=my_state, value=my_state__1, id=6) } diff --git a/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProcWithChannelDefinitions.ir b/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProcWithChannelDefinitions.ir index ef29124896..e017add27c 100644 --- a/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProcWithChannelDefinitions.ir +++ b/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProcWithChannelDefinitions.ir @@ -4,11 +4,11 @@ proc my_proc<>(my_token: token, my_state: bits[32], init={token, 42}) { chan ch(bits[32], id=0, kind=streaming, ops=send_receive, flow_control=none, strictness=proven_mutually_exclusive) chan_interface ch(direction=send, kind=streaming, flow_control=ready_valid, flop_kind=none) chan_interface ch(direction=receive, kind=streaming, flow_control=ready_valid, flop_kind=none) - my_token: token = state_read(state_element=my_token, id=6) - my_state: bits[32] = state_read(state_element=my_state, id=7) - send.1: token = send(my_token, my_state, channel=ch, id=1) + my_token__1: token = state_read(state_element=my_token, id=6) + my_state__1: bits[32] = state_read(state_element=my_state, id=7) + send.1: token = send(my_token__1, my_state__1, channel=ch, id=1) receive.2: (token, bits[32]) = receive(send.1, channel=ch, id=2) tuple_index.3: token = tuple_index(receive.2, index=0, id=3) next_value.11: () = next_value(state_element=my_token, value=tuple_index.3, id=11) - next_value.12: () = next_value(state_element=my_state, value=my_state, id=12) + next_value.12: () = next_value(state_element=my_state, value=my_state__1, id=12) } diff --git a/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProcWithComplexChannelTypes.ir b/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProcWithComplexChannelTypes.ir index 632c26c443..2f46bf9761 100644 --- a/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProcWithComplexChannelTypes.ir +++ b/xls/ir/testdata/ir_parser_round_trip_test_ParseNewStyleProcWithComplexChannelTypes.ir @@ -3,12 +3,12 @@ package test proc my_proc(my_token: token, my_state: ((), bits[32][1]), init={token, ((), [42])}) { chan_interface in_ch(direction=receive, kind=single_value, strictness=proven_mutually_exclusive, flow_control=none, flop_kind=none) chan_interface out_ch(direction=send, kind=streaming, flow_control=ready_valid, flop_kind=skid) - my_token: token = state_read(state_element=my_token, id=7) - my_state: ((), bits[32][1]) = state_read(state_element=my_state, id=8) - send.1: token = send(my_token, my_state, channel=out_ch, id=1) + my_token__1: token = state_read(state_element=my_token, id=7) + my_state__1: ((), bits[32][1]) = state_read(state_element=my_state, id=8) + send.1: token = send(my_token__1, my_state__1, channel=out_ch, id=1) literal.2: bits[1] = literal(value=1, id=2) receive.3: (token, ()) = receive(send.1, predicate=literal.2, channel=in_ch, id=3) tuple_index.4: token = tuple_index(receive.3, index=0, id=4) next_value.13: () = next_value(state_element=my_token, value=tuple_index.4, id=13) - next_value.14: () = next_value(state_element=my_state, value=my_state, id=14) + next_value.14: () = next_value(state_element=my_state, value=my_state__1, id=14) } diff --git a/xls/ir/testdata/ir_parser_round_trip_test_ParseProcWithExplicitNext.ir b/xls/ir/testdata/ir_parser_round_trip_test_ParseProcWithExplicitNext.ir index df5b47b9e7..8b4383f3a7 100644 --- a/xls/ir/testdata/ir_parser_round_trip_test_ParseProcWithExplicitNext.ir +++ b/xls/ir/testdata/ir_parser_round_trip_test_ParseProcWithExplicitNext.ir @@ -3,12 +3,12 @@ package test chan ch(bits[32], id=0, kind=streaming, ops=send_receive, flow_control=none, strictness=proven_mutually_exclusive) proc my_proc(my_token: token, my_state: bits[32], init={token, 42}) { - my_token: token = state_read(state_element=my_token, id=9) - my_state: bits[32] = state_read(state_element=my_state, id=10) - send.1: token = send(my_token, my_state, channel=ch, id=1) + my_token__1: token = state_read(state_element=my_token, id=9) + my_state__1: bits[32] = state_read(state_element=my_state, id=10) + send.1: token = send(my_token__1, my_state__1, channel=ch, id=1) literal.2: bits[1] = literal(value=1, id=2) receive.3: (token, bits[32]) = receive(send.1, predicate=literal.2, channel=ch, id=3) tuple_index.4: token = tuple_index(receive.3, index=0, id=4) next_value.5: () = next_value(state_element=my_token, value=tuple_index.4, id=5) - next_value.6: () = next_value(state_element=my_state, value=my_state, id=6) + next_value.6: () = next_value(state_element=my_state, value=my_state__1, id=6) } diff --git a/xls/ir/testdata/ir_parser_round_trip_test_ParseProcWithPredicatedStateRead.ir b/xls/ir/testdata/ir_parser_round_trip_test_ParseProcWithPredicatedStateRead.ir index 0583e15d06..5d305d6eef 100644 --- a/xls/ir/testdata/ir_parser_round_trip_test_ParseProcWithPredicatedStateRead.ir +++ b/xls/ir/testdata/ir_parser_round_trip_test_ParseProcWithPredicatedStateRead.ir @@ -3,14 +3,14 @@ package test chan ch(bits[32], id=0, kind=streaming, ops=send_receive, flow_control=none, strictness=proven_mutually_exclusive) proc my_proc(my_token: token, my_state: bits[32], my_predicate: bits[1], init={token, 42, 1}) { - my_predicate: bits[1] = state_read(state_element=my_predicate, id=18) - my_token: token = state_read(state_element=my_token, id=9) - my_state: bits[32] = state_read(state_element=my_state, predicate=my_predicate, id=10) - send.1: token = send(my_token, my_state, channel=ch, id=1) + my_predicate__1: bits[1] = state_read(state_element=my_predicate, id=18) + my_token__1: token = state_read(state_element=my_token, id=9) + my_state__1: bits[32] = state_read(state_element=my_state, predicate=my_predicate__1, id=10) + send.1: token = send(my_token__1, my_state__1, channel=ch, id=1) literal.2: bits[1] = literal(value=1, id=2) receive.3: (token, bits[32]) = receive(send.1, predicate=literal.2, channel=ch, id=3) tuple_index.4: token = tuple_index(receive.3, index=0, id=4) next_value.5: () = next_value(state_element=my_token, value=tuple_index.4, id=5) - next_value.6: () = next_value(state_element=my_state, value=my_state, id=6) - next_value.7: () = next_value(state_element=my_predicate, value=my_predicate, id=7) + next_value.6: () = next_value(state_element=my_state, value=my_state__1, id=6) + next_value.7: () = next_value(state_element=my_predicate, value=my_predicate__1, id=7) } diff --git a/xls/ir/testdata/ir_parser_round_trip_test_ParseScheduledProc.ir b/xls/ir/testdata/ir_parser_round_trip_test_ParseScheduledProc.ir index b43b4fe690..9cad7b39cc 100644 --- a/xls/ir/testdata/ir_parser_round_trip_test_ParseScheduledProc.ir +++ b/xls/ir/testdata/ir_parser_round_trip_test_ParseScheduledProc.ir @@ -2,9 +2,9 @@ package my_package scheduled_proc my_proc(st: bits[32], init={42}) { stage { - st: bits[32] = state_read(state_element=st, id=1) + st__1: bits[32] = state_read(state_element=st, id=1) literal.2: bits[32] = literal(value=1, id=2) - add.3: bits[32] = add(literal.2, st, id=3) + add.3: bits[32] = add(literal.2, st__1, id=3) next_value.4: () = next_value(state_element=st, value=add.3, id=4) } } diff --git a/xls/ir/testdata/ir_parser_round_trip_test_ParseSimpleProc.ir b/xls/ir/testdata/ir_parser_round_trip_test_ParseSimpleProc.ir index ff6bc50b7c..73470e7eab 100644 --- a/xls/ir/testdata/ir_parser_round_trip_test_ParseSimpleProc.ir +++ b/xls/ir/testdata/ir_parser_round_trip_test_ParseSimpleProc.ir @@ -3,12 +3,12 @@ package test chan ch(bits[32], id=0, kind=streaming, ops=send_receive, flow_control=none, strictness=proven_mutually_exclusive) proc my_proc(my_token: token, my_state: bits[32], init={token, 42}) { - my_token: token = state_read(state_element=my_token, id=7) - my_state: bits[32] = state_read(state_element=my_state, id=8) - send.1: token = send(my_token, my_state, channel=ch, id=1) + my_token__1: token = state_read(state_element=my_token, id=7) + my_state__1: bits[32] = state_read(state_element=my_state, id=8) + send.1: token = send(my_token__1, my_state__1, channel=ch, id=1) literal.2: bits[1] = literal(value=1, id=2) receive.3: (token, bits[32]) = receive(send.1, predicate=literal.2, channel=ch, id=3) tuple_index.4: token = tuple_index(receive.3, index=0, id=4) next_value.13: () = next_value(state_element=my_token, value=tuple_index.4, id=13) - next_value.14: () = next_value(state_element=my_state, value=my_state, id=14) + next_value.14: () = next_value(state_element=my_state, value=my_state__1, id=14) } diff --git a/xls/tools/delay_info_main_test.py b/xls/tools/delay_info_main_test.py index 717ad46c9b..dff4e0164b 100644 --- a/xls/tools/delay_info_main_test.py +++ b/xls/tools/delay_info_main_test.py @@ -144,14 +144,9 @@ def test_decoupled_next_proc(self): '--pipeline_stages=1', ir_file.full_path, ]).decode('utf-8') - print(output) self.assertIn('# Critical path for state element __state', output) - self.assertIn( - '__state: bits[32] = state_read(state_element=__state,', output - ) - self.assertIn( - 'add: bits[32] = add(__state: bits[32], one: bits[32],', output - ) + self.assertIn('sr: bits[32] = state_read(state_element=__state,', output) + self.assertIn('add: bits[32] = add(sr: bits[32], one: bits[32],', output) self.assertIn('next_state: () = next_value(state_element=__state,', output) diff --git a/xls/tools/eval_proc_main_proc_scoped_test.py b/xls/tools/eval_proc_main_proc_scoped_test.py index 1583cc179f..7c78f2a3e7 100644 --- a/xls/tools/eval_proc_main_proc_scoped_test.py +++ b/xls/tools/eval_proc_main_proc_scoped_test.py @@ -1332,13 +1332,15 @@ def test_observe_proc(self, backend): node_stats( node_id=4, node_text=( - "send.4: token = send(literal.2, st, channel=out, id=4)" + "send.4: token = send(literal.2, st__1, channel=out, id=4)" ), set_bits=TOKEN, ), node_stats( node_id=78, - node_text="st: bits[32] = state_read(state_element=st, id=78)", + node_text=( + "st__1: bits[32] = state_read(state_element=st, id=78)" + ), set_bits=_value_32_bits(0b11), total_bit_count=32, unset_bit_count=30,