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/ -v
See 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)