@startuml
skinparam componentStyle rectangle
skinparam shadowing false
skinparam monochrome false
title Modular OCaml simulation components

package "Scenario JSON" {
  [PCS Scenario]
  [USM Scenario]
}

package "OCaml DES Core" {
  [Workload Generator] as Workload
  [Scheduler / Admission] as Scheduler
  [Scaling Controller] as Scaler
  [SST-style Event Bus] as EventBus
}

package "Protocol / Device Models" {
  [RoCE-v2 RDMA Packet Model] as RoCE
  [OpenZFS TXG Model] as TXG
  [GPU Kernel Model] as GPU
  [Metadata / Backpressure Model] as META
}

package "Outputs" {
  [timeline.csv]
  [rdma_packets.csv]
  [openzfs_txg.csv]
  [gpu_kernels.csv]
  [sst_events.csv]
  [scaling_decisions.csv]
  [summary.json]
}

[PCS Scenario] --> Workload
[USM Scenario] --> Workload
Workload --> Scheduler : arrivals
Scheduler --> RoCE : RDMA_READ / RDMA_WRITE / SEND batches
Scheduler --> GPU : prefill / decode / checksum kernels
Scheduler --> TXG : dirty bytes / blocks
Scheduler --> META : metadata ops
RoCE --> Scaler : p99 latency, utilization, ECN/CNP/PFC
GPU --> Scaler : kernel p99, utilization
TXG --> Scaler : dirty limit, sync lag, commit timing
META --> Scaler : p99 latency, queue age
Scaler --> Scheduler : vertical/horizontal/both action
Scheduler --> EventBus
RoCE --> EventBus
GPU --> EventBus
TXG --> EventBus
META --> EventBus
EventBus --> [sst_events.csv]
RoCE --> [rdma_packets.csv]
GPU --> [gpu_kernels.csv]
TXG --> [openzfs_txg.csv]
Scaler --> [scaling_decisions.csv]
Scheduler --> [timeline.csv]
Scaler --> [summary.json]
@enduml
