Skip to content

fix: move simtime forward on the read after a write - #614

Open
Sahil-u07 wants to merge 1 commit into
ControlCore-Project:devfrom
Sahil-u07:fix/simtime-end-of-run
Open

Sahil-u07 wants to merge 1 commit into
ControlCore-Project:devfrom
Sahil-u07:fix/simtime-end-of-run

Conversation

@Sahil-u07

Copy link
Copy Markdown
Contributor

Fixes #608

Since #431 write() doesn't touch simtime, so a node only moves its clock when it reads. A plant that writes with delta=1 can't reach maxtime by itself anymore, and if the controller finishes first and writes its init values back to the port before the plant has read the last real value, the plant gets stuck one step before the end. More details and the repro are in #608.

I went with the first option from the issue:

During a normal run this gives the same simtime as before since the next read would have brought it there anyway. The only difference is at the very end, where the slower node can do one more step with the reset value before it stops, instead of hanging.

Done the same way in Python (concore_base.py), C++ (concore.hpp, concoredocker.hpp), Java, MATLAB/Octave and Julia (concore.jl, concoredocker.jl), each with a small test that fails on dev:

  • tests/test_end_of_run.py runs a controller and a slower plant as two processes, same shape as testsou/cpymat.py / pmpymat.py. On dev the plant never finishes, with this it passes in ~2s
  • unit tests in tests/test_concore.py, TestConcoreHpp.cpp, TestConcoreApi.java, tests/julia/test_protocol.jl and a new tests/matlab/test_write_advance.m (added to the existing MATLAB step in CI)

The phase 1 conformance runner now clears the pending write before the read cases, since those cases expect a fresh node.

Verilog isn't in here yet. readdata in concore.v still overwrites simtime with whatever it reads, so this would be undone right away. That's fixed in #604, I'll add the Verilog part once that's in.

Before

The new test against dev:

before

After

after

Since ControlCore-Project#431 write() no longer touches simtime, so a node only moves its
clock when it reads. A plant that writes with delta=1 never reaches
maxtime by itself any more. If its controller finishes first and writes
its init values back to the port before the plant has read the last
real value, the plant reads the reset value, stays one step short of
maxtime and waits forever (ControlCore-Project#608). It shows up when the plant is a bit
slower than the controller, e.g. on Windows or with MATLAB/Verilog.

write() still leaves simtime alone, so writes in the same step keep the
same timestamp (ControlCore-Project#385). It now remembers simtime + delta, and the next
read moves simtime up to that before reading. If simtime was changed
in between (initval, or set by hand) the pending advance is dropped.

Done the same way in Python, C++ (concore.hpp, concoredocker.hpp),
Java, MATLAB/Octave and Julia (concore.jl, concoredocker.jl), with a
test in each. tests/test_end_of_run.py runs a controller and a slower
plant as two processes and hangs without this change. Verilog needs
ControlCore-Project#604 first since readdata still overwrites simtime there.

Fixes ControlCore-Project#608
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.

1 participant