Skip to content

Commit

Permalink
Fix for IO conditions in pipelined loops in FSM mode.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 605452944
  • Loading branch information
Sean Purser-Haskell authored and copybara-github committed Feb 9, 2024
1 parent e55d8a1 commit bea249d
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 2 deletions.
20 changes: 18 additions & 2 deletions xls/contrib/xlscc/translate_block.cc
Original file line number Diff line number Diff line change
Expand Up @@ -973,13 +973,20 @@ absl::StatusOr<Translator::SubFSMReturn> Translator::GenerateSubFSM(
outer_prepared.xls_func->return_value_count, body_loc);

xls::BValue context_out = pb.TupleIndex(ret_io_value, /*idx=*/0, body_loc);
xls::BValue enter_condition =
pb.TupleIndex(ret_io_value, /*idx=*/1, body_loc);
XLS_CHECK_EQ(enter_condition.GetType()->GetFlatBitCount(), 1);

// Generate inner FSM
XLS_ASSIGN_OR_RETURN(
PipelinedLoopContentsReturn contents_ret,
GenerateIR_PipelinedLoopContents(
*sub_proc_invoked, pb, outer_prepared.token, context_out,
/*in_state_condition=*/outer_state.in_this_state,
/*in_state_condition=*/
pb.And(outer_state.in_this_state, enter_condition, body_loc,
/*name=*/
absl::StrFormat("%s_loop_contents_condition",
sub_proc_invoked->name_prefix)),
/*in_fsm=*/true));

outer_prepared.token = contents_ret.token_out;
Expand All @@ -1001,8 +1008,17 @@ absl::StatusOr<Translator::SubFSMReturn> Translator::GenerateSubFSM(
absl::StrFormat("%s_state_%i_context_receive_invoke", fsm_prefix,
outer_state.index));

xls::BValue not_enter_condition = pb.Not(
enter_condition, body_loc,
/*name=*/
absl::StrFormat("%s_not_enter_condition", sub_proc_invoked->name_prefix));

return SubFSMReturn{
.exit_state_condition = contents_ret.do_break,
.exit_state_condition =
pb.Or(not_enter_condition, contents_ret.do_break, body_loc,
/*name=*/
absl::StrFormat("%s_not_exit_state_condition",
sub_proc_invoked->name_prefix)),
.return_value = context_receive_ret_val,
.extra_next_state_values = contents_ret.extra_next_state_values};
}
Expand Down
125 changes: 125 additions & 0 deletions xls/contrib/xlscc/unit_tests/translator_proc_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6678,6 +6678,131 @@ TEST_P(TranslatorProcTest, PipelinedLoopSerialDataDependency) {
}
}

TEST_P(TranslatorProcTest, PipelinedLoopConditionFalse) {
const std::string content = R"(
class Block {
public:
__xls_channel<int, __xls_channel_dir_In>& in;
__xls_channel<int, __xls_channel_dir_Out>& out;
#pragma hls_top
void Run() {
int value = in.read();
#pragma hls_pipeline_init_interval 1
for(int i=0;i<0;++i) {
out.write(55);
}
#pragma hls_pipeline_init_interval 1
for(int i=0;i<6;++i) {
out.write(value++);
}
}
};)";

absl::flat_hash_map<std::string, std::list<xls::Value>> inputs;
inputs["in"] = {xls::Value(xls::SBits(11, 32))};

{
absl::flat_hash_map<std::string, std::list<xls::Value>> outputs;
outputs["out"] = {
xls::Value(xls::SBits(11 + 0, 32)), xls::Value(xls::SBits(11 + 1, 32)),
xls::Value(xls::SBits(11 + 2, 32)), xls::Value(xls::SBits(11 + 3, 32)),
xls::Value(xls::SBits(11 + 4, 32)), xls::Value(xls::SBits(11 + 5, 32))};
ProcTest(content, /*block_spec=*/std::nullopt, inputs, outputs,
/* min_ticks = */ 1,
/* max_ticks = */ 100,
/* top_level_init_interval = */ 1);
}
}

TEST_P(TranslatorProcTest, PipelinedLoopConditional) {
const std::string content = R"(
class Block {
public:
__xls_channel<int, __xls_channel_dir_In>& in;
__xls_channel<int, __xls_channel_dir_Out>& out;
#pragma hls_top
void Run() {
int value = in.read();
if(0) {
#pragma hls_pipeline_init_interval 1
for(int i=0;i<0;++i) {
out.write(55);
}
}
if(1) {
#pragma hls_pipeline_init_interval 1
for(int i=0;i<6;++i) {
out.write(value++);
}
}
}
};)";

absl::flat_hash_map<std::string, std::list<xls::Value>> inputs;
inputs["in"] = {xls::Value(xls::SBits(11, 32))};

{
absl::flat_hash_map<std::string, std::list<xls::Value>> outputs;
outputs["out"] = {
xls::Value(xls::SBits(11 + 0, 32)), xls::Value(xls::SBits(11 + 1, 32)),
xls::Value(xls::SBits(11 + 2, 32)), xls::Value(xls::SBits(11 + 3, 32)),
xls::Value(xls::SBits(11 + 4, 32)), xls::Value(xls::SBits(11 + 5, 32))};
ProcTest(content, /*block_spec=*/std::nullopt, inputs, outputs,
/* min_ticks = */ 1,
/* max_ticks = */ 100,
/* top_level_init_interval = */ 1);
}
}

TEST_P(TranslatorProcTest, PipelinedLoopConditional2) {
const std::string content = R"(
class Block {
public:
__xls_channel<int, __xls_channel_dir_In>& in;
__xls_channel<int, __xls_channel_dir_Out>& out;
#pragma hls_top
void Run() {
int value = in.read();
if(0) {
#pragma hls_pipeline_init_interval 1
for(int i=0;i<1;++i) {
++value;
}
}
if(1) {
#pragma hls_pipeline_init_interval 1
for(int i=0;i<6;++i) {
out.write(value++);
}
}
}
};)";

absl::flat_hash_map<std::string, std::list<xls::Value>> inputs;
inputs["in"] = {xls::Value(xls::SBits(11, 32))};

{
absl::flat_hash_map<std::string, std::list<xls::Value>> outputs;
outputs["out"] = {
xls::Value(xls::SBits(11 + 0, 32)), xls::Value(xls::SBits(11 + 1, 32)),
xls::Value(xls::SBits(11 + 2, 32)), xls::Value(xls::SBits(11 + 3, 32)),
xls::Value(xls::SBits(11 + 4, 32)), xls::Value(xls::SBits(11 + 5, 32))};
ProcTest(content, /*block_spec=*/std::nullopt, inputs, outputs,
/* min_ticks = */ 1,
/* max_ticks = */ 100,
/* top_level_init_interval = */ 1);
}
}

TEST_P(TranslatorProcTest, PipelinedLoopSerialAfterASAP) {
const std::string content = R"(
class Block {
Expand Down

0 comments on commit bea249d

Please sign in to comment.