diff --git a/samples/cxl_mem_tg/cxl_mem_tg.h b/samples/cxl_mem_tg/cxl_mem_tg.h index 03b335d8bdc6..94a6f22f396c 100644 --- a/samples/cxl_mem_tg/cxl_mem_tg.h +++ b/samples/cxl_mem_tg/cxl_mem_tg.h @@ -41,7 +41,7 @@ static const uint64_t KB = 1024; static const uint64_t MB = KB * 1024; static const uint64_t GB = MB * 1024; static const uint64_t FPGA_32GB_CACHE_LINES = (32 * GB) / 64; -static const uint64_t MEM_TG_TEST_TIMEOUT = 3000000; +static const uint64_t MEM_TG_TEST_TIMEOUT = 500000; static const uint64_t TEST_SLEEP_INVL = 100; static const uint64_t TG_CTRL_CLEAR = 0x8000000000000000; static const uint64_t TG_SLEEP = 300 / 1000; @@ -292,5 +292,19 @@ class cxl_mem_tg : public test_afu { } token::ptr_t get_token() { return handle_->get_token(); } + + bool option_passed(string str) { + CLI::Option* opt = app_.get_option_no_throw(str); + if (opt && opt->count() == 1) { + return true; + } + return false; + } + + uint64_t get_timeout() { + return timeout_msec_; + } + + }; } // end of namespace cxl_mem_tg diff --git a/samples/cxl_mem_tg/cxl_tg_test.h b/samples/cxl_mem_tg/cxl_tg_test.h index a8b0a557b554..55a35b17c4ed 100644 --- a/samples/cxl_mem_tg/cxl_tg_test.h +++ b/samples/cxl_mem_tg/cxl_tg_test.h @@ -34,6 +34,7 @@ #include #include #include +#include #include "afu_test.h" #include "cxl_mem_tg.h" @@ -74,7 +75,7 @@ namespace cxl_mem_tg { class cxl_tg_test : public test_command { public: - cxl_tg_test() : tg_offset_(0x0), tg_exe_(NULL) {} + cxl_tg_test() : tg_offset_(0x0), timeout_usec_(MEM_TG_TEST_TIMEOUT), tg_exe_(NULL) {} virtual ~cxl_tg_test() {} @@ -92,6 +93,34 @@ class cxl_tg_test : public test_command { ((1000.0 / (double)(tg_exe_->mem_speed_/1000) * (double)num_ticks)); } + int ofs_wait_for_eq32(uint32_t offset, uint32_t value, + uint64_t timeout_usec, uint32_t sleep_usec) { + OFS_TIMESPEC_USEC(ts, sleep_usec); + struct timespec begin, now, save, rem; + save = ts; + uint32_t csr; + csr = tg_exe_->read32(offset); + clock_gettime(CLOCK_MONOTONIC, &begin); + while (csr != value) { + if (sleep_usec) { + ts = save; + while ((nanosleep(&ts, &rem) == -1) && + (errno == EINTR)) + ts = rem; + } + csr = tg_exe_->read32(offset); + clock_gettime(CLOCK_MONOTONIC, &now); + struct timespec delta; + ofs_diff_timespec(&delta, &now, &begin); + uint64_t delta_nsec = delta.tv_nsec + delta.tv_sec * SEC2NSEC; + if (delta_nsec > timeout_usec * USEC2NSEC) { + return 1; + } + } + return 0; + + } + void print_he_mem_tg() { tg_exe_->logger_->debug("DFH:0x{:x}", tg_exe_->read64(AFU_DFH)); tg_exe_->logger_->debug("GUIDL:0x{:x}", tg_exe_->read64(AFU_ID_L)); @@ -215,20 +244,16 @@ class cxl_tg_test : public test_command { uint32_t tg_fail = 0; tg_exe_->logger_->debug("tg wait for test completion..."); - tg_status = tg_exe_->read32(TG_TEST_COMPLETE); - tg_exe_->logger_->debug("test complete status:{}", tg_status); - - while (tg_status != 0x1) { - tg_status = tg_exe_->read32(TG_TEST_COMPLETE); - std::this_thread::yield(); - if (--timeout == 0) { + int ret = ofs_wait_for_eq32(TG_TEST_COMPLETE, 0x1, + timeout_usec_, TEST_SLEEP_INVL); + if (ret != 0) { std::cerr << "test completion timeout " << std::endl; tg_exe_->status_ = -1; tg_print_fail_info(); return false; - } } + tg_exe_->logger_->debug("test complete status:{}", tg_exe_->read32(TG_TEST_COMPLETE)); tg_exe_->logger_->debug("tg pass:{}", tg_exe_->read32(TG_PASS)); tg_fail = tg_exe_->read32(TG_FAIL); @@ -303,7 +328,13 @@ class cxl_tg_test : public test_command { return -1; } - if (tg_exe_->rcnt_ > tg_exe_->wcnt_) { + if (tg_exe_->option_passed("--timeout")) { + timeout_usec_ = tg_exe_->get_timeout() * 1000; + } + + if (tg_exe_->option_passed("--writes") && + tg_exe_->option_passed("--reads") && + (tg_exe_->rcnt_ > tg_exe_->wcnt_)) { cerr << "Read count exceeds Write count" << endl; return -1; } @@ -448,6 +479,7 @@ class cxl_tg_test : public test_command { protected: uint64_t tg_offset_; + uint64_t timeout_usec_; cxl_mem_tg *tg_exe_; };