A simulation framework for imprecisely time-correlated endpoints.
SysMesh provides a framework for building simulations composed of multiple endpoints that communicate via uni-directional FIFO connections. Endpoints are loosely time-synchronized within a configurable delta tolerance, making it suitable for modeling systems where components don't need precise cycle-accurate synchronization.
- Loose time synchronization: Endpoints advance within
deltatime units of each other - Callback-based execution: Controllers call endpoint advance callbacks
- FIFO-based communication: Uni-directional ports with backpressure
- Simple C API: Clean C99 API for integration
- Python bindings: High-level Python API with support for async/await patterns
mkdir build && cd build
cmake ..
make
sudo make install#include <sysmesh.h>
void my_endpoint_advance(sm_endpoint_t *ep, uint64_t limit, void *ud) {
// Process incoming data
uintptr_t data;
while (sm_ingress_get(ep->ingress, &data)) {
// Handle data
}
// Advance time and produce output
while (ep->time < limit) {
// Do work...
sm_egress_put(ep->egress, output_data, NULL, NULL);
ep->time++;
}
}
int main() {
// Create controller with delta=100
sm_controller_t ctrl;
sm_controller_init(&ctrl, 100);
// Create endpoint
sm_endpoint_t ep;
sm_endpoint_init(&ep, "my_endpoint", &ctrl, my_endpoint_advance, NULL);
// Add ports
sm_ingress_t *ing = sm_ingress_init(&ep, "in", 16);
sm_egress_t *egr = sm_egress_init(&ep, "out");
// Advance simulation
sm_controller_adv(&ctrl, 1000);
// Cleanup
sm_endpoint_fini(&ep);
sm_controller_fini(&ctrl);
return 0;
}from sysmesh import Controller, Endpoint
class MyEndpoint:
def __init__(self, name, controller):
self.endpoint = Endpoint(name, controller, self.advance)
self.ingress = self.endpoint.add_ingress("in", size=16)
self.egress = self.endpoint.add_egress("out")
def advance(self, ep, limit):
# Process incoming data
while self.ingress.has_data():
data = self.ingress.get()
if data is not None:
# Handle data
pass
# Advance time and produce output
while ep.time < limit:
# Do work...
self.egress.put(output_data)
ep.time += 1
# Create controller
ctrl = Controller(delta=100)
# Create endpoints
ep1 = MyEndpoint("endpoint1", ctrl)
ep2 = MyEndpoint("endpoint2", ctrl)
# Connect endpoints
ep1.egress.bind(ep2.ingress)
# Run simulation
ctrl.advance(1000)- Manages multiple endpoints
- Advances simulation time
- Coordinates endpoint execution with delta tolerance
- Iterates until all endpoints reach target time or have no pending data
- Execute via advance callback:
sm_advreq_f(ep, limit, ud) - Callback must return when:
ep->time >= limit, OR- Producing output, OR
- Blocked on input
- Track local time independently
- Ingress: Input port with FIFO buffer
- Egress: Output port connected to peer ingress
- Binding: Permanent uni-directional connection
- Circular buffer implementation
- Backpressure when full
- Optional ack callback when space becomes available
- Single-threaded: No locking required
- Permanent bindings: Ports connected once, never unbound
- Loose synchronization: Endpoints within
deltaof each other - Simple memory model:
_initallocates,_finifrees
# C library tests (if added)
cd build && ctest
# Python tests
python -m pytest tests/unit/ -vSee tests/unit/test_bidirectional.py for a complete example of two endpoints communicating bidirectionally, where:
- Endpoint A produces data every 10 time units
- Endpoint B produces data every 100 time units
- Both endpoints process received data
See LICENSE file.
Contributions welcome! Please ensure:
- C code compiles without warnings
- All tests pass
- New features include tests
- Documentation updated
Version 0.1.0 - Initial implementation
- ✓ Core C library
- ✓ Python bindings
- ✓ Basic tests
- ⧖ Async/await support (planned)
- ⧖ Additional language bindings (planned)