1 // -*- mode: C++; c-file-style: "cc-mode" -*- 2 //************************************************************************* 3 // 4 // Copyright 2018-2018 by Wilson Snyder. This program is free software; you can 5 // redistribute it and/or modify it under the terms of either the GNU 6 // Lesser General Public License Version 3 or the Perl Artistic License 7 // Version 2.0. 8 // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 9 // 10 //************************************************************************* 11 12 #include <atomic> 13 #include <cstdio> 14 #include <iostream> 15 #include <unistd.h> 16 #include "svdpi.h" 17 18 //====================================================================== 19 20 // clang-format off 21 #if defined(VERILATOR) 22 # ifdef T_DPI_THREADS_COLLIDE 23 # include "Vt_dpi_threads_collide__Dpi.h" 24 # else 25 # include "Vt_dpi_threads__Dpi.h" 26 # endif 27 #elif defined(VCS) 28 # include "../vc_hdrs.h" 29 #elif defined(CADENCE) 30 # define NEED_EXTERNS 31 #else 32 # error "Unknown simulator for DPI test" 33 #endif 34 // clang-format on 35 36 #ifdef NEED_EXTERNS 37 extern "C" { 38 extern void dpii_sys_task(); 39 extern int dpii_failure(); 40 } 41 #endif 42 43 //====================================================================== 44 45 struct state { 46 std::atomic<bool> task_is_running; 47 std::atomic<int> failure; statestate48 state() 49 : task_is_running(false) 50 , failure(false) {} 51 }; 52 53 static state st; 54 dpii_sys_task()55void dpii_sys_task() { 56 bool other_task_running = atomic_exchange(&st.task_is_running, true); 57 if (other_task_running) { 58 // Another task is running. This is a collision. 59 st.failure = 1; 60 std::cerr << "t_dpi_threads_c.cpp dpii_sys_task() saw threads collide.\n"; 61 } else { 62 std::cerr << "t_dpi_threads_c.cpp dpii_sys_task() no collision. @" << &st.task_is_running 63 << "\n"; 64 } 65 66 // Spend some time in the DPI call, so that if we can have a collision 67 // we probably will. Technically this is not guaranteed to detect every 68 // race. However, one second is so much greater than the expected 69 // runtime of everything else in the test, it really should pick up on 70 // races just about all of the time. 71 sleep(1); 72 73 atomic_exchange(&st.task_is_running, false); 74 } 75 dpii_failure()76int dpii_failure() { return st.failure; } 77