Skip to content

Commit b3771c2

Browse files
committed
Correct CSR pipe behaviour when StallFree is used
1 parent ce17087 commit b3771c2

File tree

6 files changed

+95
-59
lines changed

6 files changed

+95
-59
lines changed

include/acl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,9 @@ struct acl_hostpipe_mapping {
542542

543543
int protocol = -1; // avalon_streaming = 0, avalon_streaming_uses_ready = 1
544544
// avalon_mm = 2, avalon_mm_uses_ready = 3
545+
546+
// Introduced in 2024.2
547+
int is_stall_free = -1; // -1 means unset, set value is 0 or 1;
545548
};
546549

547550
// Mapping of sideband signals to logical pipe

include/acl_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@ typedef struct host_pipe_struct {
349349
// Sideband signals vector
350350
std::vector<sideband_signal_t> side_band_signals_vector;
351351

352+
// Introduced in 2024.2
353+
int is_stall_free = -1; // -1 means unset, set value is 0 or 1;
354+
352355
} host_pipe_t;
353356

354357
// The device-specific information about a program.

src/acl_auto_configure.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,13 @@ static bool read_hostpipe_mappings(
668668
mapping.protocol, counters);
669669
}
670670

671+
// Start from 2024.2, there is a new field called is_stall_free in the
672+
// auto-discovery string
673+
if (result && counters.back() > 0) {
674+
result = result && read_int_counters(config_str, curr_pos,
675+
mapping.is_stall_free, counters);
676+
}
677+
671678
hostpipe_mappings.emplace_back(mapping);
672679

673680
while (result && counters.back() > 0) {

src/acl_hostch.cpp

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -823,9 +823,24 @@ void acl_read_program_hostpipe(void *user_data, acl_device_op_t *op) {
823823
acl_set_device_op_execution_status(op, CL_RUNNING);
824824

825825
if (host_pipe_info.implement_in_csr) {
826-
// CSR read, currently only blocking version is implemented
826+
// Here is the logic for CSR pipe read
827+
// Compiler initializes ready register to 1, if ready register exist
828+
// Non-Blocking uses_ready<true>
829+
// 1. if ready == 1, fail.
830+
// 2. Read data.
831+
// 3. write 1 to ready.
832+
833+
// Blocking uses_ready<true>
834+
// 1. wait until ready = 0.
835+
// 2. read data.
836+
// 3. write 1 to ready.
837+
838+
// uses_ready<false>
839+
// Both Blocking and NonBlocking
840+
// 1. Read data (always succeeds)
841+
827842
unsigned long long parsed;
828-
uintptr_t data_reg, ready_reg, valid_reg;
843+
uintptr_t data_reg, ready_reg;
829844
// Convert the CSR address to a pointer
830845
try {
831846
parsed = std::stoull(host_pipe_info.csr_address, nullptr);
@@ -839,27 +854,21 @@ void acl_read_program_hostpipe(void *user_data, acl_device_op_t *op) {
839854
ready_reg = static_cast<uintptr_t>(
840855
parsed +
841856
csr_pipe_address_offet); // ready reg is data reg shift by 8 byte
842-
valid_reg = static_cast<uintptr_t>(
843-
parsed +
844-
csr_pipe_address_offet * 2); // valid reg is ready reg shift by 8 byte
845857
unsigned ready = 1;
846-
unsigned valid_value;
847-
unsigned *valid_value_pointer = &valid_value;
858+
unsigned ready_value;
859+
unsigned *ready_value_pointer = &ready_value;
848860

849-
// protocol 3 is the avalon_mm_uses_ready protocol
850-
// Only this uses_ready protocol requires reading/writing to ready&valid
851-
// signals
852-
if (host_pipe_info.protocol == 3) {
853-
// If Blocking, wait until the data is valid.
854-
// If Non-blocking, just read once and report failure if not valid.
861+
if (host_pipe_info.is_stall_free == 0) {
862+
// If Blocking, wait until the ready register = 0
863+
// If Non-blocking, just read once and report failure if ready == 1
855864
do {
856-
acl_get_hal()->read_csr(host_pipe_info.m_physical_device_id, valid_reg,
857-
(void *)valid_value_pointer,
865+
acl_get_hal()->read_csr(host_pipe_info.m_physical_device_id, ready_reg,
866+
(void *)ready_value_pointer,
858867
(size_t)sizeof(uintptr_t));
859-
} while (blocking && valid_value != 1);
868+
} while (blocking && ready_value != 0);
860869

861-
// If non-blocking and valid bit is not set, set the op to fail.
862-
if (!blocking && valid_value == 0) {
870+
// If non-blocking and ready bit is 1, set the op to fail.
871+
if (!blocking && ready_value == 1) {
863872
acl_mutex_unlock(&(host_pipe_info.m_lock));
864873
acl_set_device_op_execution_status(op, -1);
865874
return;
@@ -875,9 +884,8 @@ void acl_read_program_hostpipe(void *user_data, acl_device_op_t *op) {
875884
acl_set_device_op_execution_status(op, -1);
876885
return;
877886
}
878-
// Tell CSR it's ready
879-
// Same reason as above, only avalon_mm_uses_ready needs to do this.
880-
if (host_pipe_info.protocol == 3) {
887+
// Tell CSR it's ready if ready register exist
888+
if (host_pipe_info.is_stall_free == 0) {
881889
acl_get_hal()->write_csr(host_pipe_info.m_physical_device_id, ready_reg,
882890
(void *)&ready, (size_t)sizeof(uintptr_t));
883891
}
@@ -968,10 +976,19 @@ void acl_write_program_hostpipe(void *user_data, acl_device_op_t *op) {
968976
// Get CSR address
969977

970978
// Here is the logic for CSR pipe write
971-
// 1. If blocking, read valid reg, wait until valid is 0.
972-
// 2. If non-blocking, read valid reg once ->return failure if valid is 1.
973-
// 3. write to the pipe.
974-
// 4. write 1 to the valid.
979+
// Blocking uses_valid<true>:
980+
// 1. read valid reg, wait until valid is 0
981+
// 2. write to the pipe.
982+
// 3. write 1 to the valid.
983+
984+
// Non-blocking uses_valid<true>
985+
// 1. read valid reg once ->return failure if valid is 1
986+
// 2. write to the pipe.
987+
// 3. write 1 to the valid.
988+
989+
// uses_valid<false>
990+
// Both Blocking and NonBlocking
991+
// 1. Write data (always succeeds)
975992

976993
unsigned long long parsed;
977994
uintptr_t data_reg, valid_reg;
@@ -990,23 +1007,24 @@ void acl_write_program_hostpipe(void *user_data, acl_device_op_t *op) {
9901007
unsigned valid_value = 1;
9911008
unsigned *valid_value_pointer = &valid_value;
9921009

993-
if (blocking) {
994-
// Wait until the valid reg is 0, before the write.
995-
while (valid_value != 0) {
1010+
if (host_pipe_info.is_stall_free == 0) {
1011+
if (blocking) {
1012+
while (valid_value != 0) {
1013+
acl_get_hal()->read_csr(host_pipe_info.m_physical_device_id,
1014+
valid_reg, (void *)valid_value_pointer,
1015+
(size_t)sizeof(uintptr_t));
1016+
}
1017+
} else {
1018+
// Non-blocking, if valid reg is 1, return failure.
9961019
acl_get_hal()->read_csr(host_pipe_info.m_physical_device_id, valid_reg,
9971020
(void *)valid_value_pointer,
9981021
(size_t)sizeof(uintptr_t));
999-
}
1000-
} else {
1001-
// Non-blocking, if valid reg is 1, return failure.
1002-
acl_get_hal()->read_csr(host_pipe_info.m_physical_device_id, valid_reg,
1003-
(void *)valid_value_pointer,
1004-
(size_t)sizeof(uintptr_t));
10051022

1006-
if (valid_value == 1) {
1007-
acl_mutex_unlock(&(host_pipe_info.m_lock));
1008-
acl_set_device_op_execution_status(op, -1);
1009-
return;
1023+
if (valid_value == 1) {
1024+
acl_mutex_unlock(&(host_pipe_info.m_lock));
1025+
acl_set_device_op_execution_status(op, -1);
1026+
return;
1027+
}
10101028
}
10111029
}
10121030

@@ -1015,19 +1033,18 @@ void acl_write_program_hostpipe(void *user_data, acl_device_op_t *op) {
10151033
host_pipe_info.m_physical_device_id, data_reg,
10161034
event->cmd.info.host_pipe_dynamic_info.write_ptr,
10171035
event->cmd.info.host_pipe_dynamic_info.size);
1036+
10181037
if (status != 0) {
10191038
acl_mutex_unlock(&(host_pipe_info.m_lock));
10201039
acl_set_device_op_execution_status(op, -1);
10211040
return;
10221041
}
10231042

1024-
// For now, we trust the AVALON_MM by default uses valid.
1025-
// TODO: fix this later by using the new protocol info
1026-
// provided by the compiler.
1027-
1028-
const unsigned valid = 1;
1029-
acl_get_hal()->write_csr(host_pipe_info.m_physical_device_id, valid_reg,
1030-
(void *)&valid, (size_t)sizeof(uintptr_t));
1043+
if (host_pipe_info.is_stall_free == 0) {
1044+
const unsigned valid = 1;
1045+
acl_get_hal()->write_csr(host_pipe_info.m_physical_device_id, valid_reg,
1046+
(void *)&valid, (size_t)sizeof(uintptr_t));
1047+
}
10311048

10321049
} else {
10331050
// Regular hostpipe

src/acl_program.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,6 +1364,7 @@ l_register_hostpipes_to_program(acl_device_program_info_t *dev_prog,
13641364
}
13651365
}
13661366
host_pipe_info.protocol = hostpipe.protocol;
1367+
host_pipe_info.is_stall_free = hostpipe.is_stall_free;
13671368
acl_mutex_init(&(host_pipe_info.m_lock), NULL);
13681369
// The following property is not used by the program scoped hostpipe but we
13691370
// don't want to leave it uninitialized

test/acl_auto_configure_test.cpp

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,14 +1496,14 @@ TEST(auto_configure, cra_ring_root_exist) {
14961496

14971497
TEST(auto_configure, hostpipe_mappings) {
14981498
const std::string config_str{
1499-
"23 71 " RANDOM_HASH
1499+
"23 76 " RANDOM_HASH
15001500
" pac_a10 0 1 13 DDR 2 2 24 1 2 0 4294967296 4294967296 8589934592 0 - 0 "
1501-
"0 0 0 0 0 1 5 9 " // 5 Hostpipes, 9 in each mapping
1502-
"pipe_logical_name1 pipe_physical_name1 1 12345 0 1 4 10 0 "
1503-
"pipe_logical_name2 pipe_physical_name2 0 12323 1 0 8 20 1 "
1504-
"pipe_logical_name3 pipe_physical_name1 1 12313 0 1 4 10 2 "
1505-
"pipe_logical_name5 pipe_physical_name1 0 12316 1 0 8 20 3 "
1506-
"pipe_logical_name4 pipe_physical_name3 0 12342 0 1 4 10 3 "
1501+
"0 0 0 0 0 1 5 10 " // 5 Hostpipes, 10 in each mapping
1502+
"pipe_logical_name1 pipe_physical_name1 1 12345 0 1 4 10 0 0 "
1503+
"pipe_logical_name2 pipe_physical_name2 0 12323 1 0 8 20 1 1 "
1504+
"pipe_logical_name3 pipe_physical_name1 1 12313 0 1 4 10 2 0 "
1505+
"pipe_logical_name5 pipe_physical_name1 0 12316 1 0 8 20 3 1 "
1506+
"pipe_logical_name4 pipe_physical_name3 0 12342 0 1 4 10 3 0 "
15071507
"3 90 "
15081508
"_ZTS3CRCILi0EE 512 256 1 0 0 1 0 1 0 9 6 0 0 8 1 0 0 6 2 1 8 1024 0 3 6 "
15091509
"0 0 8 1 0 0 6 0 0 8 1 0 0 6 0 0 8 1 0 0 6 2 1 8 1024 0 2 6 0 0 8 1 0 0 "
@@ -1538,6 +1538,7 @@ TEST(auto_configure, hostpipe_mappings) {
15381538
CHECK(devdef.hostpipe_mappings[0].pipe_width == 4);
15391539
CHECK(devdef.hostpipe_mappings[0].pipe_depth == 10);
15401540
CHECK(devdef.hostpipe_mappings[0].protocol == 0);
1541+
CHECK(devdef.hostpipe_mappings[0].is_stall_free == 0);
15411542

15421543
CHECK(devdef.hostpipe_mappings[1].logical_name == "pipe_logical_name2");
15431544
CHECK(devdef.hostpipe_mappings[1].physical_name == "pipe_physical_name2");
@@ -1548,6 +1549,7 @@ TEST(auto_configure, hostpipe_mappings) {
15481549
CHECK(devdef.hostpipe_mappings[1].pipe_width == 8);
15491550
CHECK(devdef.hostpipe_mappings[1].pipe_depth == 20);
15501551
CHECK(devdef.hostpipe_mappings[1].protocol == 1);
1552+
CHECK(devdef.hostpipe_mappings[1].is_stall_free == 1);
15511553

15521554
CHECK(devdef.hostpipe_mappings[2].logical_name == "pipe_logical_name3");
15531555
CHECK(devdef.hostpipe_mappings[2].physical_name == "pipe_physical_name1");
@@ -1558,6 +1560,7 @@ TEST(auto_configure, hostpipe_mappings) {
15581560
CHECK(devdef.hostpipe_mappings[2].pipe_width == 4);
15591561
CHECK(devdef.hostpipe_mappings[2].pipe_depth == 10);
15601562
CHECK(devdef.hostpipe_mappings[2].protocol == 2);
1563+
CHECK(devdef.hostpipe_mappings[2].is_stall_free == 0);
15611564

15621565
CHECK(devdef.hostpipe_mappings[3].logical_name == "pipe_logical_name5");
15631566
CHECK(devdef.hostpipe_mappings[3].physical_name == "pipe_physical_name1");
@@ -1568,6 +1571,7 @@ TEST(auto_configure, hostpipe_mappings) {
15681571
CHECK(devdef.hostpipe_mappings[3].pipe_width == 8);
15691572
CHECK(devdef.hostpipe_mappings[3].pipe_depth == 20);
15701573
CHECK(devdef.hostpipe_mappings[3].protocol == 3);
1574+
CHECK(devdef.hostpipe_mappings[3].is_stall_free == 1);
15711575

15721576
CHECK(devdef.hostpipe_mappings[4].logical_name == "pipe_logical_name4");
15731577
CHECK(devdef.hostpipe_mappings[4].physical_name == "pipe_physical_name3");
@@ -1578,18 +1582,19 @@ TEST(auto_configure, hostpipe_mappings) {
15781582
CHECK(devdef.hostpipe_mappings[4].pipe_width == 4);
15791583
CHECK(devdef.hostpipe_mappings[4].pipe_depth == 10);
15801584
CHECK(devdef.hostpipe_mappings[4].protocol == 3);
1585+
CHECK(devdef.hostpipe_mappings[4].is_stall_free == 0);
15811586
}
15821587

15831588
TEST(auto_configure, sideband_mappings) {
15841589
const std::string config_str{
1585-
"23 102 " RANDOM_HASH
1590+
"23 107 " RANDOM_HASH
15861591
" pac_a10 0 1 13 DDR 2 2 24 1 2 0 4294967296 4294967296 8589934592 0 - 0 "
1587-
"0 0 0 0 0 1 5 9 " // 5 Hostpipes, 9 in each mapping
1588-
"pipe_logical_name1 pipe_physical_name1 1 12345 0 1 4 10 0 "
1589-
"pipe_logical_name2 pipe_physical_name2 0 12323 1 0 8 20 1 "
1590-
"pipe_logical_name3 pipe_physical_name1 1 12313 0 1 4 10 2 "
1591-
"pipe_logical_name5 pipe_physical_name1 0 12316 1 0 8 20 3 "
1592-
"pipe_logical_name4 pipe_physical_name3 0 12342 0 1 4 10 3 "
1592+
"0 0 0 0 0 1 5 10 " // 5 Hostpipes, 10 in each mapping
1593+
"pipe_logical_name1 pipe_physical_name1 1 12345 0 1 4 10 0 0 "
1594+
"pipe_logical_name2 pipe_physical_name2 0 12323 1 0 8 20 1 1 "
1595+
"pipe_logical_name3 pipe_physical_name1 1 12313 0 1 4 10 2 0 "
1596+
"pipe_logical_name5 pipe_physical_name1 0 12316 1 0 8 20 3 1 "
1597+
"pipe_logical_name4 pipe_physical_name3 0 12342 0 1 4 10 3 0 "
15931598
"2 " // 2 Sideband groups
15941599
"pipe_logical_name1 4 3 0 0 320 1 320 8 2 328 8 3 352 32 "
15951600
"pipe_logical_name2 4 3 0 0 320 1 320 8 2 328 8 3 352 32 "

0 commit comments

Comments
 (0)