flatbuffer base
This commit is contained in:
11
flatbuffers/auth/auth.fbs
Normal file
11
flatbuffers/auth/auth.fbs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace hmmmm.auth;
|
||||
|
||||
// Client → Server: SHA-512(access_token + str(unix_timestamp / 30))
|
||||
table AuthRequest {
|
||||
hash: [ubyte]; // 64 bytes
|
||||
}
|
||||
|
||||
// Server → Client: seat assigned, current emulation state echoed
|
||||
table AuthResponse {
|
||||
seat_id: uint64;
|
||||
}
|
||||
16
flatbuffers/config/clock.fbs
Normal file
16
flatbuffers/config/clock.fbs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace hmmmm.config;
|
||||
|
||||
// Global emulator clock constraints.
|
||||
table ClockConfig {
|
||||
// Maximum emulated ticks per real second.
|
||||
// 0 = unlimited (run as fast as possible).
|
||||
limiter: uint64;
|
||||
}
|
||||
|
||||
// Clock source and frequency relationship for one device.
|
||||
// Devices form a clock tree: each node derives its frequency from its src.
|
||||
table DeviceClockConfig {
|
||||
src: string; // id of the parent device; empty = root clock
|
||||
divider: uint32 = 1;
|
||||
multiplier: uint32 = 1;
|
||||
}
|
||||
20
flatbuffers/config/config.fbs
Normal file
20
flatbuffers/config/config.fbs
Normal file
@@ -0,0 +1,20 @@
|
||||
include "device.fbs";
|
||||
include "mem_config.fbs";
|
||||
include "clock.fbs";
|
||||
|
||||
namespace hmmmm.config;
|
||||
|
||||
// Top-level emulator / system configuration.
|
||||
// Equivalent to glob.toml — describes a full composite device tree.
|
||||
//
|
||||
// File use: flatcc -a config/config.fbs → binary system config files
|
||||
// WS use: embed in ConfigCtrlMessage when config-change protocol is ready
|
||||
table SystemConfig {
|
||||
devices: [DeviceEntry]; // ordered list; id must be unique
|
||||
clock: ClockConfig;
|
||||
projections: [Projection];
|
||||
intercepts: [Intercept];
|
||||
mem_setup: [MemSetup];
|
||||
}
|
||||
|
||||
root_type SystemConfig;
|
||||
39
flatbuffers/config/device.fbs
Normal file
39
flatbuffers/config/device.fbs
Normal file
@@ -0,0 +1,39 @@
|
||||
include "mem_config.fbs";
|
||||
include "clock.fbs";
|
||||
|
||||
namespace hmmmm.config;
|
||||
|
||||
// Configuration for a single base device (leaf node in the device tree).
|
||||
// Equivalent to a standalone device TOML (e.g. AVRrc.toml, gpio.toml).
|
||||
table BaseDeviceConfig {
|
||||
libpath: string;
|
||||
mem_segments: [MemSegment];
|
||||
}
|
||||
|
||||
// Override for one memory segment within a child device.
|
||||
// Only fields that need changing from the base config must be set.
|
||||
table MemSegOverride {
|
||||
segment: string;
|
||||
start: uint32;
|
||||
len: uint32;
|
||||
word_len: uint8;
|
||||
executable: bool;
|
||||
}
|
||||
|
||||
// One device entry in a composite configuration.
|
||||
table DeviceEntry {
|
||||
// Local identifier, unique within this composite (e.g. "core", "gpio_a").
|
||||
id: string;
|
||||
|
||||
// Exactly one of config or config_path must be set.
|
||||
// config: inline base device configuration.
|
||||
// config_path: path to a serialised BaseDeviceConfig FlatBuffer file.
|
||||
config: BaseDeviceConfig;
|
||||
config_path: string;
|
||||
|
||||
clock: DeviceClockConfig;
|
||||
overrides: [MemSegOverride];
|
||||
}
|
||||
|
||||
// Root type when serialising a standalone device config to a binary file.
|
||||
root_type BaseDeviceConfig;
|
||||
73
flatbuffers/config/mem_config.fbs
Normal file
73
flatbuffers/config/mem_config.fbs
Normal file
@@ -0,0 +1,73 @@
|
||||
namespace hmmmm.config;
|
||||
|
||||
// Named offset within a segment — symbolic variable for protocol/tool use
|
||||
// (e.g. PIN=0, PORT=1, DDR=2 in a GPIO device).
|
||||
table NamedOffset {
|
||||
name: string;
|
||||
offset: uint32;
|
||||
}
|
||||
|
||||
// A contiguous memory segment within a base device.
|
||||
table MemSegment {
|
||||
name: string;
|
||||
start: uint32; // base address in device flat address space
|
||||
len: uint32;
|
||||
word_len: uint8 = 1; // word size in bytes
|
||||
executable: bool = false;
|
||||
variables: [NamedOffset]; // optional symbolic offsets within segment
|
||||
}
|
||||
|
||||
// ── Projections ──────────────────────────────────────────────────────────────
|
||||
|
||||
// Maps a segment from one device into the flat address space of another.
|
||||
// After projection, accesses to [base_seg + shift .. shift+len) in base_at
|
||||
// are transparently forwarded to target_at:target_seg.
|
||||
table Projection {
|
||||
base_at: string; // device where the projection appears
|
||||
base_seg: string; // segment in that device that is the projection window
|
||||
target_at: string; // device owning the real data
|
||||
target_seg: string;
|
||||
shift: uint32 = 0; // offset from base_seg start
|
||||
}
|
||||
|
||||
// ── Intercepts ───────────────────────────────────────────────────────────────
|
||||
|
||||
enum InterceptOp: byte {
|
||||
op_read = 0,
|
||||
op_write = 1,
|
||||
op_both = 2,
|
||||
}
|
||||
|
||||
enum InterceptMode: byte {
|
||||
shadow_copy = 1, // duplicate write to point_at:point_addr as well
|
||||
shadow_replace = 2, // redirect access to point_at:point_addr instead
|
||||
callback = 3, // invoke a handler registered by point_at device
|
||||
}
|
||||
|
||||
table Intercept {
|
||||
name: string;
|
||||
op: InterceptOp = op_both;
|
||||
mode: InterceptMode = callback;
|
||||
base_at: string; // device where the triggering access occurs
|
||||
base_seg: string;
|
||||
base_addr: uint32;
|
||||
point_at: string; // device that handles/receives the intercept
|
||||
point_seg: string;
|
||||
point_addr: uint32;
|
||||
}
|
||||
|
||||
// ── Memory initialisation ─────────────────────────────────────────────────────
|
||||
|
||||
enum OverflowBehaviour: byte {
|
||||
overflow_error = 0, // abort if file is larger than segment
|
||||
overflow_ignore = 1, // stop reading at segment end, no error
|
||||
overflow_wrap = 2, // wrap around and continue writing from segment start
|
||||
}
|
||||
|
||||
// Load initial segment contents from a file (e.g. firmware binary, /dev/urandom).
|
||||
table MemSetup {
|
||||
device: string;
|
||||
segment: string;
|
||||
filepath: string;
|
||||
overflow: OverflowBehaviour = overflow_error;
|
||||
}
|
||||
8
flatbuffers/control/config_ctrl.fbs
Normal file
8
flatbuffers/control/config_ctrl.fbs
Normal file
@@ -0,0 +1,8 @@
|
||||
// Config change control — WIP.
|
||||
// Schema stub; content will be defined when the config-change sub-protocol
|
||||
// is specified (requires device-loading control in the protocol first).
|
||||
namespace hmmmm.ctrl.config_ctrl;
|
||||
|
||||
table ConfigCtrlMessage {
|
||||
// TODO
|
||||
}
|
||||
37
flatbuffers/control/config_notif.fbs
Normal file
37
flatbuffers/control/config_notif.fbs
Normal file
@@ -0,0 +1,37 @@
|
||||
namespace hmmmm.ctrl.config_notif;
|
||||
|
||||
// Notification subtype 0001 — a device's configuration was updated.
|
||||
// Carries the path of the affected device; client should re-request full config.
|
||||
table DeviceConfigUpdateNotif {
|
||||
device_path: [string]; // hierarchical path, e.g. ["core"] or ["gpio_a"]
|
||||
}
|
||||
|
||||
// Numeric ID assigned to one named segment within a device.
|
||||
table SegIdEntry {
|
||||
name: string;
|
||||
id: uint32;
|
||||
}
|
||||
|
||||
// Maps a hierarchical device path to a compact numeric device_id + segment IDs.
|
||||
// Clients use these IDs in stream and mem packets instead of string paths.
|
||||
table DeviceIdEntry {
|
||||
path: [string]; // hierarchical device id, e.g. ["core"]
|
||||
device_id: uint32;
|
||||
seg_ids: [SegIdEntry];
|
||||
}
|
||||
|
||||
// Notification subtype 0010 — full device-id / segment-id mapping table.
|
||||
// Sent after auth and after any config change that affects the device tree.
|
||||
table DeviceIdMappingNotif {
|
||||
entries: [DeviceIdEntry];
|
||||
}
|
||||
|
||||
union ConfigNotifPayload {
|
||||
DeviceConfigUpdateNotif,
|
||||
DeviceIdMappingNotif,
|
||||
}
|
||||
|
||||
table ConfigNotifMessage {
|
||||
tclk: uint64;
|
||||
payload: ConfigNotifPayload;
|
||||
}
|
||||
39
flatbuffers/control/control.fbs
Normal file
39
flatbuffers/control/control.fbs
Normal file
@@ -0,0 +1,39 @@
|
||||
include "exec_ctrl.fbs";
|
||||
include "exec_notif.fbs";
|
||||
include "config_ctrl.fbs";
|
||||
include "config_notif.fbs";
|
||||
include "lost.fbs";
|
||||
include "orphaned.fbs";
|
||||
include "setup_buf.fbs";
|
||||
include "qos.fbs";
|
||||
|
||||
namespace hmmmm.ctrl;
|
||||
|
||||
// ── Client → Server ──────────────────────────────────────────────────────────
|
||||
|
||||
union CtrlClientPayload {
|
||||
hmmmm.ctrl.exec.ExecCtrlMessage,
|
||||
hmmmm.ctrl.config_ctrl.ConfigCtrlMessage,
|
||||
hmmmm.ctrl.lost.LostMessagesRequest,
|
||||
hmmmm.ctrl.orphaned.OrphanedRequest,
|
||||
hmmmm.ctrl.setup_buf.SetupBuf,
|
||||
}
|
||||
|
||||
table CtrlClientMessage {
|
||||
payload: CtrlClientPayload;
|
||||
}
|
||||
|
||||
// ── Server → Client ──────────────────────────────────────────────────────────
|
||||
|
||||
union CtrlServerPayload {
|
||||
hmmmm.ctrl.exec_notif.ExecNotifyMessage,
|
||||
hmmmm.ctrl.config_notif.ConfigNotifMessage,
|
||||
hmmmm.ctrl.lost.LostMessagesResponse,
|
||||
hmmmm.ctrl.orphaned.OrphanedResponse,
|
||||
hmmmm.ctrl.setup_buf.SetupBuf,
|
||||
hmmmm.ctrl.qos.QosReport,
|
||||
}
|
||||
|
||||
table CtrlServerMessage {
|
||||
payload: CtrlServerPayload;
|
||||
}
|
||||
14
flatbuffers/control/exec_ctrl.fbs
Normal file
14
flatbuffers/control/exec_ctrl.fbs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace hmmmm.ctrl.exec;
|
||||
|
||||
enum ExecPrompt: byte {
|
||||
_invalid = 0,
|
||||
start = 1,
|
||||
pause = 2,
|
||||
resume = 3,
|
||||
stop = 4,
|
||||
reset = 5,
|
||||
}
|
||||
|
||||
table ExecCtrlMessage {
|
||||
prompt: ExecPrompt;
|
||||
}
|
||||
13
flatbuffers/control/exec_notif.fbs
Normal file
13
flatbuffers/control/exec_notif.fbs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace hmmmm.ctrl.exec_notif;
|
||||
|
||||
enum ExecState: byte {
|
||||
still = 0,
|
||||
executing = 1,
|
||||
paused = 2,
|
||||
stopped = 3,
|
||||
}
|
||||
|
||||
table ExecNotifyMessage {
|
||||
tclk: uint64;
|
||||
state: ExecState;
|
||||
}
|
||||
19
flatbuffers/control/lost.fbs
Normal file
19
flatbuffers/control/lost.fbs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace hmmmm.ctrl.lost;
|
||||
|
||||
// Client → Server: request buffered (undelivered) messages for a seat.
|
||||
table LostMessagesRequest {
|
||||
seat_id: uint64;
|
||||
clear: bool = false; // if true, drop the buffer after reading
|
||||
}
|
||||
|
||||
// One buffered message that was not delivered before the seat disconnected.
|
||||
table LostMessage {
|
||||
original_nonce: uint64;
|
||||
data: [ubyte]; // raw FlatBuffer bytes of the original ServerMessage
|
||||
}
|
||||
|
||||
// Server → Client: buffered messages for the requested seat.
|
||||
table LostMessagesResponse {
|
||||
seat_id: uint64;
|
||||
messages: [LostMessage];
|
||||
}
|
||||
16
flatbuffers/control/orphaned.fbs
Normal file
16
flatbuffers/control/orphaned.fbs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace hmmmm.ctrl.orphaned;
|
||||
|
||||
// Client → Server: enumerate disconnected seats that still have buffered messages.
|
||||
// No body — request is the signal itself.
|
||||
table OrphanedRequest {}
|
||||
|
||||
table OrphanedEntry {
|
||||
seat_id: uint64;
|
||||
disconnect_tclk: uint64; // virtual clock tick at time of disconnect
|
||||
lost_count: uint32; // number of buffered messages waiting
|
||||
}
|
||||
|
||||
// Server → Client: list of orphaned seats with pending buffers.
|
||||
table OrphanedResponse {
|
||||
entries: [OrphanedEntry];
|
||||
}
|
||||
10
flatbuffers/control/qos.fbs
Normal file
10
flatbuffers/control/qos.fbs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace hmmmm.ctrl.qos;
|
||||
|
||||
// Server → Client: connection quality snapshot.
|
||||
// Sent periodically or on request (TBD).
|
||||
table QosReport {
|
||||
rtt_us: uint64; // measured round-trip time, microseconds
|
||||
packets_sent: uint64;
|
||||
packets_lost: uint32;
|
||||
buf_pressure: float; // outgoing buffer fill level, 0.0 .. 1.0
|
||||
}
|
||||
8
flatbuffers/control/setup_buf.fbs
Normal file
8
flatbuffers/control/setup_buf.fbs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace hmmmm.ctrl.setup_buf;
|
||||
|
||||
// Client → Server: configure the lost-message buffer for this seat.
|
||||
// Server → Client: echoes back the confirmed (possibly clamped) settings.
|
||||
table SetupBuf {
|
||||
lost_buf_size: uint32; // max buffered messages per seat
|
||||
client_lifetime_ticks: uint64; // virtual ticks to keep buffer after disconnect
|
||||
}
|
||||
46
flatbuffers/mem/mem.fbs
Normal file
46
flatbuffers/mem/mem.fbs
Normal file
@@ -0,0 +1,46 @@
|
||||
namespace hmmmm.mem;
|
||||
|
||||
// Client → Server: read a contiguous memory region. Server responds with
|
||||
// MemReadResponse carrying the same nonce as the enclosing ClientMessage.
|
||||
table MemReadRequest {
|
||||
device_id: uint32;
|
||||
seg_id: uint32;
|
||||
offset: uint32;
|
||||
length: uint32;
|
||||
}
|
||||
|
||||
// Server → Client: memory region contents at the moment of the read.
|
||||
table MemReadResponse {
|
||||
tclk: uint64; // virtual clock tick at time of read
|
||||
device_id: uint32;
|
||||
seg_id: uint32;
|
||||
offset: uint32;
|
||||
data: [ubyte];
|
||||
}
|
||||
|
||||
// Client → Server: write a contiguous memory region. No response.
|
||||
table MemWriteRequest {
|
||||
device_id: uint32;
|
||||
seg_id: uint32;
|
||||
offset: uint32;
|
||||
data: [ubyte];
|
||||
}
|
||||
|
||||
// ── Unions ───────────────────────────────────────────────────────────────────
|
||||
|
||||
union MemClientPayload {
|
||||
MemReadRequest,
|
||||
MemWriteRequest,
|
||||
}
|
||||
|
||||
table MemClientMessage {
|
||||
payload: MemClientPayload;
|
||||
}
|
||||
|
||||
union MemServerPayload {
|
||||
MemReadResponse,
|
||||
}
|
||||
|
||||
table MemServerMessage {
|
||||
payload: MemServerPayload;
|
||||
}
|
||||
42
flatbuffers/proto.fbs
Normal file
42
flatbuffers/proto.fbs
Normal file
@@ -0,0 +1,42 @@
|
||||
include "auth/auth.fbs";
|
||||
include "control/control.fbs";
|
||||
include "stream/stream.fbs";
|
||||
include "mem/mem.fbs";
|
||||
|
||||
namespace hmmmm;
|
||||
|
||||
// ── Client → Server ──────────────────────────────────────────────────────────
|
||||
|
||||
union ClientPayload {
|
||||
hmmmm.auth.AuthRequest,
|
||||
hmmmm.ctrl.CtrlClientMessage,
|
||||
hmmmm.stream.StreamClientMessage,
|
||||
hmmmm.mem.MemClientMessage,
|
||||
}
|
||||
|
||||
// Every frame sent by the client is a ClientMessage.
|
||||
// nonce: client-chosen identifier echoed in the server response.
|
||||
// Use 0xFFFFFFFFFFFFFFFF for fire-and-forget messages (no reply expected).
|
||||
table ClientMessage {
|
||||
nonce: uint64;
|
||||
payload: ClientPayload;
|
||||
}
|
||||
|
||||
// ── Server → Client ──────────────────────────────────────────────────────────
|
||||
|
||||
union ServerPayload {
|
||||
hmmmm.auth.AuthResponse,
|
||||
hmmmm.ctrl.CtrlServerMessage,
|
||||
hmmmm.stream.StreamServerMessage,
|
||||
hmmmm.mem.MemServerMessage,
|
||||
}
|
||||
|
||||
// Every frame sent by the server is a ServerMessage.
|
||||
// nonce: echoes the triggering ClientMessage nonce.
|
||||
// 0xFFFFFFFFFFFFFFFF for unsolicited notifications (state changes, stream pushes).
|
||||
table ServerMessage {
|
||||
nonce: uint64;
|
||||
payload: ServerPayload;
|
||||
}
|
||||
|
||||
root_type ClientMessage;
|
||||
27
flatbuffers/stream/stream.fbs
Normal file
27
flatbuffers/stream/stream.fbs
Normal file
@@ -0,0 +1,27 @@
|
||||
include "stream_reg.fbs";
|
||||
include "stream_data.fbs";
|
||||
|
||||
namespace hmmmm.stream;
|
||||
|
||||
// ── Client → Server ──────────────────────────────────────────────────────────
|
||||
|
||||
union StreamClientPayload {
|
||||
StreamRegRequest,
|
||||
StreamDeregRequest,
|
||||
StreamWritePush,
|
||||
}
|
||||
|
||||
table StreamClientMessage {
|
||||
payload: StreamClientPayload;
|
||||
}
|
||||
|
||||
// ── Server → Client ──────────────────────────────────────────────────────────
|
||||
|
||||
union StreamServerPayload {
|
||||
StreamRegConfirm,
|
||||
StreamDataPush,
|
||||
}
|
||||
|
||||
table StreamServerMessage {
|
||||
payload: StreamServerPayload;
|
||||
}
|
||||
18
flatbuffers/stream/stream_data.fbs
Normal file
18
flatbuffers/stream/stream_data.fbs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace hmmmm.stream;
|
||||
|
||||
// Server → Client: memory region snapshot pushed by the server.
|
||||
// tclk is the virtual clock tick at which this data became valid —
|
||||
// clients may buffer and apply it at the appropriate simulation point.
|
||||
table StreamDataPush {
|
||||
stream_id: uint32;
|
||||
tclk: uint64;
|
||||
data: [ubyte];
|
||||
}
|
||||
|
||||
// Client → Server: write into a registered write-mode stream.
|
||||
// offset is relative to the registered region start.
|
||||
table StreamWritePush {
|
||||
stream_id: uint32;
|
||||
offset: uint32;
|
||||
data: [ubyte];
|
||||
}
|
||||
32
flatbuffers/stream/stream_reg.fbs
Normal file
32
flatbuffers/stream/stream_reg.fbs
Normal file
@@ -0,0 +1,32 @@
|
||||
namespace hmmmm.stream;
|
||||
|
||||
enum StreamMode: byte {
|
||||
mode_read = 0,
|
||||
mode_write = 1,
|
||||
}
|
||||
|
||||
// Client → Server: subscribe to a memory region.
|
||||
table StreamRegRequest {
|
||||
device_id: uint32; // from DeviceIdMappingNotif
|
||||
seg_id: uint32; // from DeviceIdMappingNotif
|
||||
offset: uint32; // start offset within segment, in bytes
|
||||
length: uint32; // region length, in bytes
|
||||
mode: StreamMode;
|
||||
}
|
||||
|
||||
// Client → Server: cancel a stream subscription.
|
||||
// No confirmation is sent by the server.
|
||||
table StreamDeregRequest {
|
||||
stream_id: uint32;
|
||||
}
|
||||
|
||||
// Server → Client: subscription confirmed, stream_id assigned.
|
||||
// Echoes the original request fields for client-side reconciliation.
|
||||
table StreamRegConfirm {
|
||||
stream_id: uint32;
|
||||
device_id: uint32;
|
||||
seg_id: uint32;
|
||||
offset: uint32;
|
||||
length: uint32;
|
||||
mode: StreamMode;
|
||||
}
|
||||
Reference in New Issue
Block a user