Skip to content

XVC: event-driven refactor + CI regression test#1182

Open
ruck314 wants to merge 5 commits intopre-releasefrom
EmuFpgaXvc
Open

XVC: event-driven refactor + CI regression test#1182
ruck314 wants to merge 5 commits intopre-releasefrom
EmuFpgaXvc

Conversation

@ruck314
Copy link
Copy Markdown
Contributor

@ruck314 ruck314 commented Apr 14, 2026

Summary

  • C++ event-driven refactor of rogue.protocols.xilinx.Xvc: replaces usleep(1000) + queue polling with blocking Queue::pop, self-pipe wakeFd for prompt select() shutdown (< 50 ms), getPort() accessor, MSG_NOSIGNAL in write paths, GIL release across blocking sections. Public Python API unchanged.
  • Python test harness + CI gate: pure-stdlib XvcClient, deterministic FakeJtag (ris.Master+ris.Slave) scan-chain emulator, pytest E2E cases covering getinfo / settck / shift (widths 1,7,8,9,15,16,17,32,64), chunking over supVecLen_, clean teardown (listening socket unreachable after _stop()), unknown-command handling, parallel-worker safety via port 0 + getPort(). Picked up automatically by the existing Rogue Tests (pytest) and Rogue Native C++ Tests (ctest) steps in rogue_ci.yml on Ubuntu and macOS — full_build_test gates gen_release / conda_build_lib / docker_build_rogue via the existing needs: chain.
  • Pins a Python tstate onto Xvc::runThread via ScopedGil and wraps the select() sites in XvcServer::run / XvcConnection::readTo in GilRelease so Python ris.Slave subclasses can call back into self._sendFrame from native-thread context without the fatal PyThreadState_Get crash.
  • Drops leftover tests/**/__init__.py markers that turned tests/ into a package and broke from conftest import MemoryRoot in tests/core/ plus a name collision between the two xilinx test dirs under -n auto.

Test plan

  • ./scripts/run_linters.sh clean (flake8 + cpplint, compileall green)
  • Local-install build per slaclab docs (cmake -S . -B build -DROGUE_INSTALL=local -DROGUE_BUILD_TESTS=ON && cmake --build build -j && cmake --build build --target install)
  • ctest --test-dir build -L cpp
  • pytest -n auto --dist loadfile tests/protocols/xilinx/ tests/python/protocols/xilinx/
  • pytest -n auto --dist loadfile -m "not perf"

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the Xilinx XVC server implementation to be event-driven (blocking queue + self-pipe wake) and adds an end-to-end Python test harness plus CI gating to prevent regressions.

Changes:

  • Replaces polling/timeouts with blocking waits and a wake-fd for fast shutdown; adds getPort() and expands GIL management around blocking sections.
  • Adds pure-stdlib XVC client + deterministic FakeJtag emulator and a comprehensive pytest suite (unit framing + E2E protocol coverage).
  • Adds a C++ smoke test and a dedicated “Rogue XVC Protocol Tests” CI step.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/rogue/protocols/xilinx/Xvc.cpp Event-driven refactor, wake-fd shutdown, GIL handling, getPort() binding.
src/rogue/protocols/xilinx/XvcServer.cpp Listener loop updated to block in select() and wake via self-pipe.
src/rogue/protocols/xilinx/XvcConnection.cpp Connection read loop updated to block in select(), use wake-fd, and avoid SIGPIPE.
src/rogue/protocols/xilinx/JtagDriver.cpp Makes done_ atomic and uses atomic loads in retry loop.
include/rogue/protocols/xilinx/Xvc.h Adds wake-fd/server members, atomic threadEn_, and getPort() API doc.
include/rogue/protocols/xilinx/XvcServer.h Updates ctor/run signatures for wake-fd + atomic run flag; adds getPort().
include/rogue/protocols/xilinx/XvcConnection.h Updates ctor/readTo contract for wake-fd and shutdown semantics.
include/rogue/protocols/xilinx/JtagDriver.h Makes done_ atomic and updates isDone() accordingly.
tests/protocols/xilinx/xvc_client.py Pure-stdlib XVC wire client used by tests (no Rogue import).
tests/protocols/xilinx/fake_jtag.py Deterministic scan-chain emulator (ris.Master/Slave) for stream-graph tests.
tests/protocols/xilinx/conftest.py XVC E2E fixtures: starts Xvc(0), wires FakeJtag, yields bound port.
tests/protocols/xilinx/test_xvc_e2e.py End-to-end protocol tests over real TCP against the C++ Xvc server.
tests/protocols/xilinx/test_xvc_client_framing.py Socketpair-based byte-level framing/parse tests for XvcClient.
tests/protocols/xilinx/test_fake_jtag.py Unit tests for FakeJtag oracle + frame layout + error paths.
tests/python/protocols/xilinx/test_xvc_api.py Python API smoke: preserved surface, getPort(), and basic GIL-release check.
tests/conftest.py Adds xdist-aware port-range slicing and an xvc_server fixture.
tests/cpp/protocols/xilinx/test_xvc_smoke.cpp Doctest smoke for stop latency (wake-fd) with/without a client.
tests/cpp/protocols/xilinx/CMakeLists.txt Registers the new C++ smoke test.
tests/cpp/protocols/CMakeLists.txt Adds protocols subdir when Python is enabled.
tests/cpp/CMakeLists.txt Includes protocols tests under the NO_PYTHON guard.
docs/src/built_in_modules/protocols/xilinx/index.rst Documents Vivado default port and dynamic port assignment via getPort().
.github/workflows/rogue_ci.yml Adds a dedicated XVC protocol test step in Ubuntu + macOS jobs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/rogue/protocols/xilinx/Xvc.cpp
Comment thread src/rogue/protocols/xilinx/XvcConnection.cpp Outdated
Comment thread tests/cpp/protocols/xilinx/test_xvc_smoke.cpp Outdated
Comment thread tests/protocols/xilinx/test_xvc_e2e.py Outdated
Comment thread src/rogue/protocols/xilinx/Xvc.cpp
Comment thread src/rogue/protocols/xilinx/Xvc.cpp Outdated
ruck314 added a commit that referenced this pull request Apr 14, 2026
- XvcConnection::readTo retries select() on EINTR (matches XvcServer::run)
  so a benign signal no longer tears down the client connection.
- Xvc::start guards against second start with a clear GeneralError; rogue::Queue::stop is irreversible so restart on the same instance is unsupported. This also makes the wake-fd drain question moot — the read end never gets re-armed under a new start.
- Xvc::xfer uses separate txFrame/rxFrame shared_ptrs so the TX frame is never released inside the GilRelease scope (no overwrite during the GIL-released section).
- Tag the C++ server thread via pthread_setname_np for OS-level diagnostics (htop, gdb info threads).
- Replace the Python thread-name leak filter with an observable
  socket-unreachability assertion: after _stop(), the kernel-assigned port
  must refuse new connections. The old filter was vacuous because the C++
  std::thread is invisible to Python's threading.enumerate().
- Smoke test drops the racy pick_free_port() helper and uses Xvc(0) +
  getPort() instead, eliminating the TOCTOU window between bind/close and
  Xvc rebind.
@ruck314 ruck314 requested a review from Copilot April 14, 2026 22:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/rogue/protocols/xilinx/XvcServer.cpp Outdated
Comment thread src/rogue/protocols/xilinx/XvcServer.cpp
Comment thread src/rogue/protocols/xilinx/XvcConnection.cpp Outdated
Comment thread src/rogue/protocols/xilinx/XvcConnection.cpp
Comment thread src/rogue/protocols/xilinx/Xvc.cpp Outdated
Comment thread src/rogue/protocols/xilinx/Xvc.cpp Outdated
ruck314 added a commit that referenced this pull request Apr 14, 2026
- Close leaked FDs in XvcServer ctor when setsockopt/bind/listen throw
  after socket() succeeds
- Close leaked FD in XvcConnection ctor when setsockopt throws after
  accept() succeeds
- Log errno on select() error in XvcServer::run() for diagnostics
- Distinguish shutdown (-1) from select error (-2) in readTo() so
  fill()/run() report accurate error messages
- Make Xvc::start() transactional: defer started_/threadEn_ flags until
  server construction and thread spawn both succeed; clean up on failure
- Fix misleading wake-fd drain comment in Xvc::stop()
@ruck314 ruck314 requested a review from Copilot April 14, 2026 22:15
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 14, 2026

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 56.10%. Comparing base (1c76af6) to head (e91db80).
⚠️ Report is 4 commits behind head on pre-release.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@               Coverage Diff               @@
##           pre-release    #1182      +/-   ##
===============================================
+ Coverage        56.05%   56.10%   +0.04%     
===============================================
  Files               70       70              
  Lines             8137     8137              
  Branches          1209     1209              
===============================================
+ Hits              4561     4565       +4     
+ Misses            3293     3291       -2     
+ Partials           283      281       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/rogue/protocols/xilinx/XvcConnection.cpp
Comment thread tests/protocols/xilinx/test_xvc_e2e.py
ruck314 added a commit that referenced this pull request Apr 14, 2026
readTo(): ::read() returning -1 (EINTR, ECONNRESET) collided with the
-1 shutdown sentinel.  Wrap in an EINTR retry loop and map remaining
socket errors to -2 so callers never confuse a read failure with a
wakeFd shutdown signal.

test_parallel_workers: add threading.Barrier so all 4 Xvc instances
stay alive until every port is recorded, eliminating the theoretical
TOCTOU window where the OS could recycle a released ephemeral port.
@ruck314 ruck314 requested a review from Copilot April 14, 2026 22:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/rogue/protocols/xilinx/Xvc.cpp Outdated
Comment thread src/rogue/protocols/xilinx/Xvc.cpp Outdated
Comment thread src/rogue/protocols/xilinx/Xvc.cpp
Comment thread src/rogue/protocols/xilinx/XvcConnection.cpp Outdated
ruck314 added a commit that referenced this pull request Apr 14, 2026
- Replace post-stop() drain loop with queue_.reset() to avoid infinite
  spin when queue is non-empty (Queue::pop returns default after stop).
- Cache bound port in atomic<uint32_t> so getPort() never races with
  stop()'s server_.reset().
- Mark instance done and close listener in runThread catch blocks so
  xfer() callers unblock and new TCP clients are refused on init/run
  failure.
- Retry send() on EINTR in XvcConnection::flush() (mirrors readTo()).
@ruck314 ruck314 requested a review from Copilot April 14, 2026 22:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/rogue/protocols/xilinx/Xvc.cpp
Comment thread src/rogue/protocols/xilinx/XvcConnection.cpp
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/rogue/protocols/xilinx/XvcServer.cpp:52

  • sockaddr_in a; is not zero-initialized before being passed to bind(). Only sin_family/sin_addr/sin_port are set, leaving the padding/unused fields uninitialized, which can trip MSan/valgrind and is technically UB. Initialize with sockaddr_in a{}; (or memset(&a, 0, sizeof(a))) before assigning fields.
    struct sockaddr_in a;
    int yes = 1;

    a.sin_family      = AF_INET;
    a.sin_addr.s_addr = INADDR_ANY;
    a.sin_port        = htons(port);

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/conftest.py
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/conftest.py Outdated
Comment thread tests/python/protocols/xilinx/test_xvc_api.py Outdated
Comment thread tests/protocols/xilinx/test_xvc_client_framing.py Outdated
ruck314 added a commit that referenced this pull request Apr 14, 2026
- Guard sys.path.insert in xvc_server fixture to avoid duplicates
- Drop flaky lower-bound assertion on time.sleep() in test_gil_release
- Catch Exception instead of BaseException in client thread wrapper
@ruck314 ruck314 requested a review from Copilot April 14, 2026 23:46
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/rogue/protocols/xilinx/Xvc.cpp
Comment thread src/rogue/protocols/xilinx/XvcConnection.cpp
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/protocols/xilinx/xvc_client.py
Comment thread tests/protocols/xilinx/test_xvc_e2e.py Outdated
Comment thread tests/protocols/xilinx/test_xvc_e2e.py Outdated
Comment thread tests/protocols/xilinx/test_xvc_e2e.py Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/rogue/protocols/xilinx/Xvc.cpp
Comment thread src/rogue/protocols/xilinx/XvcServer.cpp Outdated
ruck314 added a commit that referenced this pull request Apr 15, 2026
- Xvc::start(): reset boundPort_ to 0 in the catch block when
  std::thread creation throws, so getPort() doesn't return a stale
  port from a failed start.

- XvcServer::run(): throw GeneralError on unrecoverable select() failure
  instead of silently breaking.  The throw propagates to runThread()'s
  existing catch blocks which set done_=true, queue_.stop(), and
  server_.reset() — so xfer() callers unblock and new TCP clients are
  refused.  The previous silent break left threadEn_ true with no
  accept loop running.

Both issues flagged by GitHub Copilot review on PR #1182.
@ruck314 ruck314 requested a review from Copilot April 15, 2026 02:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/rogue/protocols/xilinx/Xvc.cpp
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread include/rogue/protocols/xilinx/XvcConnection.h Outdated
Comment thread include/rogue/protocols/xilinx/XvcConnection.h Outdated
Comment thread src/rogue/protocols/xilinx/JtagDriver.cpp Outdated
Comment thread include/rogue/protocols/xilinx/XvcServer.h Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 21 out of 21 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Refactor XVC/JTAG driver to event-driven architecture with hardened
code quality: RAII thread ownership, widened arithmetic to prevent
overflow, explicit narrowing casts, virtual destructors, and defensive
guards throughout.

Add JTAG emulator (fake_jtag.py) and comprehensive test suite covering
XVC client framing, end-to-end flows, and C++ smoke tests.
@ruck314 ruck314 marked this pull request as ready for review April 15, 2026 04:57
@ruck314 ruck314 mentioned this pull request Apr 15, 2026
5 tasks
ruck314 added 3 commits April 17, 2026 12:29
The xilinx conftest.py was adding its directory to sys.path[0],
which caused pytest to resolve 'from conftest import wait_for'
to the wrong conftest module during full test collection.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants