Skip to content

Commit 34fae5d

Browse files
committed
Merge remote-tracking branch 'origin/orchestrator/engine-ext'
2 parents 8612bed + c1d7b42 commit 34fae5d

11 files changed

Lines changed: 1252 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ if(CONFIG_ARBITER)
2121
${CMAKE_CURRENT_LIST_DIR}/lib/arbiter_accel.c
2222
)
2323

24+
zephyr_library_sources_ifdef(CONFIG_ARBITER_EVENT_DRIVEN
25+
${CMAKE_CURRENT_LIST_DIR}/lib/arbiter_event.c
26+
)
27+
28+
zephyr_library_sources_ifdef(CONFIG_ARBITER_COMPOSE
29+
${CMAKE_CURRENT_LIST_DIR}/lib/arbiter_compose.c
30+
)
31+
32+
zephyr_library_sources_ifdef(CONFIG_ARBITER_STATE_MACHINE
33+
${CMAKE_CURRENT_LIST_DIR}/lib/arbiter_state.c
34+
)
35+
2436
zephyr_include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
2537

2638
add_subdirectory_ifdef(CONFIG_ARBITER ${CMAKE_CURRENT_LIST_DIR}/subsys/arbiter)

include/arbiter/arbiter_compose.h

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/* SPDX-License-Identifier: MIT */
2+
3+
#ifndef ARBITER_COMPOSE_H_
4+
#define ARBITER_COMPOSE_H_
5+
6+
/**
7+
* @defgroup arbiter_compose Multi-Model Composition (REQ-ARCH-037)
8+
* @ingroup arbiter
9+
* @{
10+
* @brief Share facts across multiple models via a common fact bus.
11+
*
12+
* The fact bus holds a shared array of fact values. Each model is
13+
* "attached" with a mapping table that translates bus fact indices
14+
* to the model's own fact indices. ARBITER_compose_sync() pushes
15+
* bus values into all attached contexts; ARBITER_compose_eval_all()
16+
* evaluates every attached model in attachment order.
17+
*
18+
* All storage is pre-allocated — no malloc.
19+
*/
20+
21+
#include <stdint.h>
22+
#include <stdbool.h>
23+
#include <arbiter/arbiter.h>
24+
25+
#ifdef __cplusplus
26+
extern "C" {
27+
#endif
28+
29+
#ifndef CONFIG_ARBITER_MAX_MODELS
30+
#define CONFIG_ARBITER_MAX_MODELS 4
31+
#endif
32+
33+
#ifndef CONFIG_ARBITER_COMPOSE_MAX_BUS_FACTS
34+
#define CONFIG_ARBITER_COMPOSE_MAX_BUS_FACTS 64
35+
#endif
36+
37+
/** Maps one bus fact to a model fact. */
38+
struct ARBITER_fact_mapping {
39+
uint16_t bus_fact_id; /**< Index into the bus fact array. */
40+
uint16_t model_fact_id; /**< Index into the model's own fact array. */
41+
};
42+
43+
/** Per-attachment record (bus ↔ model link). */
44+
struct ARBITER_compose_attachment {
45+
struct ARBITER_ctx *ctx; /**< Model context. */
46+
const struct ARBITER_fact_mapping *mapping; /**< Mapping table. */
47+
uint16_t map_count; /**< Number of mappings. */
48+
bool active; /**< Slot occupied? */
49+
};
50+
51+
/** Shared fact bus. */
52+
struct ARBITER_fact_bus {
53+
struct ARBITER_fact_value *facts; /**< Shared fact array. */
54+
uint16_t max_facts; /**< Capacity of facts[]. */
55+
56+
struct ARBITER_compose_attachment
57+
attachments[CONFIG_ARBITER_MAX_MODELS]; /**< Attached models. */
58+
uint16_t attachment_count; /**< Active attachments. */
59+
};
60+
61+
/**
62+
* @brief Initialize a fact bus with a pre-allocated fact array.
63+
*
64+
* @param bus Bus to initialize.
65+
* @param facts Pre-allocated array of fact values.
66+
* @param max_facts Capacity of facts[].
67+
* @return ARBITER_OK on success, ARBITER_EINVAL if bus or facts is NULL.
68+
*/
69+
int ARBITER_compose_init(struct ARBITER_fact_bus *bus,
70+
struct ARBITER_fact_value *facts,
71+
uint16_t max_facts);
72+
73+
/**
74+
* @brief Attach a model context to the bus.
75+
*
76+
* @param bus Initialized fact bus.
77+
* @param ctx Model context to attach.
78+
* @param mapping Array of bus-to-model fact mappings.
79+
* @param map_count Number of entries in mapping[].
80+
* @return ARBITER_OK on success, ARBITER_EOVERFLOW if no slots available.
81+
*/
82+
int ARBITER_compose_attach(struct ARBITER_fact_bus *bus,
83+
struct ARBITER_ctx *ctx,
84+
const struct ARBITER_fact_mapping *mapping,
85+
uint16_t map_count);
86+
87+
/**
88+
* @brief Detach a model context from the bus.
89+
*
90+
* @param bus Bus.
91+
* @param ctx Context to detach.
92+
* @return ARBITER_OK on success, ARBITER_EINVAL if not found.
93+
*/
94+
int ARBITER_compose_detach(struct ARBITER_fact_bus *bus,
95+
struct ARBITER_ctx *ctx);
96+
97+
/**
98+
* @brief Set a fact value on the bus.
99+
*
100+
* @param bus Initialized fact bus.
101+
* @param fact_id Bus fact index.
102+
* @param value Value to set.
103+
* @return ARBITER_OK or ARBITER_ERANGE.
104+
*/
105+
int ARBITER_compose_set_fact(struct ARBITER_fact_bus *bus,
106+
uint16_t fact_id, int32_t value);
107+
108+
/**
109+
* @brief Push bus facts into all attached model contexts.
110+
*
111+
* For each attachment, iterates the mapping table and copies the bus
112+
* fact values into the model context's fact_values[].
113+
*
114+
* @param bus Initialized fact bus.
115+
* @return ARBITER_OK on success.
116+
*/
117+
int ARBITER_compose_sync(struct ARBITER_fact_bus *bus);
118+
119+
/**
120+
* @brief Evaluate all attached models in attachment order.
121+
*
122+
* For each attached model, takes a snapshot, evaluates, and stores
123+
* the result. Caller must provide arrays of at least
124+
* bus->attachment_count entries.
125+
*
126+
* @param bus Initialized fact bus.
127+
* @param results Pre-allocated array for results (one per attached model).
128+
* @param traces Pre-allocated array for traces (one per model, NULL entries OK).
129+
* @return ARBITER_OK on success.
130+
*/
131+
int ARBITER_compose_eval_all(struct ARBITER_fact_bus *bus,
132+
struct ARBITER_result *results,
133+
struct ARBITER_trace *traces);
134+
135+
/** @} */
136+
137+
#ifdef __cplusplus
138+
}
139+
#endif
140+
141+
#endif /* ARBITER_COMPOSE_H_ */

include/arbiter/arbiter_event.h

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/* SPDX-License-Identifier: MIT */
2+
3+
#ifndef ARBITER_EVENT_H_
4+
#define ARBITER_EVENT_H_
5+
6+
/**
7+
* @defgroup arbiter_event Event-Driven Evaluation (REQ-ARCH-036)
8+
* @ingroup arbiter
9+
* @{
10+
* @brief Watch facts for changes and trigger evaluation only when needed.
11+
*
12+
* Instead of polling on a fixed period, the event subsystem lets callers
13+
* mark specific facts as "watched". When a watched fact changes, a
14+
* pending flag is set. The runtime thread (or application) can check
15+
* ARBITER_event_pending() and skip evaluation cycles when nothing has
16+
* changed — saving CPU on idle periods.
17+
*
18+
* Implementation uses static bitmasks — no dynamic allocation.
19+
* For models with <= 32 facts a single uint32_t pair is used.
20+
* For larger models a uint8_t byte-array is used (1 bit per fact).
21+
*/
22+
23+
#include <stdint.h>
24+
#include <stdbool.h>
25+
#include <arbiter/arbiter.h>
26+
27+
#ifdef __cplusplus
28+
extern "C" {
29+
#endif
30+
31+
#ifndef CONFIG_ARBITER_MAX_FACTS
32+
#define CONFIG_ARBITER_MAX_FACTS 64
33+
#endif
34+
35+
/** Number of bytes needed to hold one bit per fact. */
36+
#define ARBITER_EVENT_MASK_BYTES \
37+
((CONFIG_ARBITER_MAX_FACTS + 7u) / 8u)
38+
39+
/** Event tracking state — embedded in or alongside an ARBITER_ctx. */
40+
struct ARBITER_event_ctx {
41+
#if CONFIG_ARBITER_MAX_FACTS <= 32
42+
uint32_t watched; /**< Bitmask of watched fact ids. */
43+
uint32_t pending; /**< Bitmask of changed watched facts. */
44+
#else
45+
uint8_t watched[ARBITER_EVENT_MASK_BYTES];
46+
uint8_t pending[ARBITER_EVENT_MASK_BYTES];
47+
#endif
48+
bool any_pending; /**< Fast flag: true if any bit in pending is set. */
49+
};
50+
51+
/**
52+
* @brief Initialize event tracking for a context.
53+
*
54+
* Clears all watched and pending flags.
55+
*
56+
* @param ectx Event context to initialize.
57+
* @return ARBITER_OK on success, ARBITER_EINVAL if ectx is NULL.
58+
*/
59+
int ARBITER_event_init(struct ARBITER_event_ctx *ectx);
60+
61+
/**
62+
* @brief Mark a fact as watched.
63+
*
64+
* @param ectx Event context.
65+
* @param fact_id Fact index (0-based, < CONFIG_ARBITER_MAX_FACTS).
66+
* @return ARBITER_OK on success, ARBITER_ERANGE if fact_id out of range.
67+
*/
68+
int ARBITER_watch_fact(struct ARBITER_event_ctx *ectx, uint16_t fact_id);
69+
70+
/**
71+
* @brief Remove a fact from the watch set.
72+
*
73+
* Also clears any pending flag for that fact.
74+
*
75+
* @param ectx Event context.
76+
* @param fact_id Fact index.
77+
* @return ARBITER_OK on success, ARBITER_ERANGE if fact_id out of range.
78+
*/
79+
int ARBITER_unwatch_fact(struct ARBITER_event_ctx *ectx, uint16_t fact_id);
80+
81+
/**
82+
* @brief Notify that a fact has changed.
83+
*
84+
* If the fact is watched, sets its pending bit and the fast flag.
85+
* If the fact is not watched, this is a no-op.
86+
*
87+
* @param ectx Event context.
88+
* @param fact_id Fact index.
89+
* @return ARBITER_OK on success, ARBITER_ERANGE if fact_id out of range.
90+
*/
91+
int ARBITER_notify_fact_changed(struct ARBITER_event_ctx *ectx,
92+
uint16_t fact_id);
93+
94+
/**
95+
* @brief Check whether any watched fact has changed since last clear.
96+
*
97+
* @param ectx Event context.
98+
* @return true if at least one watched fact has a pending change.
99+
*/
100+
bool ARBITER_event_pending(const struct ARBITER_event_ctx *ectx);
101+
102+
/**
103+
* @brief Clear all pending flags.
104+
*
105+
* Typically called after a successful evaluation cycle.
106+
*
107+
* @param ectx Event context.
108+
* @return ARBITER_OK on success, ARBITER_EINVAL if ectx is NULL.
109+
*/
110+
int ARBITER_event_clear(struct ARBITER_event_ctx *ectx);
111+
112+
/** @} */
113+
114+
#ifdef __cplusplus
115+
}
116+
#endif
117+
118+
#endif /* ARBITER_EVENT_H_ */

0 commit comments

Comments
 (0)