Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions python/bindings/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ set(HIERARCHICAL_SOURCES
${HIERARCHICAL_SRC}/worker_manager.cpp
${HIERARCHICAL_SRC}/scheduler.cpp
${HIERARCHICAL_SRC}/worker.cpp
${HIERARCHICAL_SRC}/chip_bootstrap_channel.cpp
)

nanobind_add_module(_task_interface ${BINDING_SOURCES} ${HIERARCHICAL_SOURCES})
Expand Down
41 changes: 41 additions & 0 deletions python/bindings/worker_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include <stdexcept>

#include "chip_bootstrap_channel.h"
#include "chip_worker.h"
#include "ring.h"
#include "orchestrator.h"
Expand Down Expand Up @@ -238,4 +239,44 @@ inline void bind_worker(nb::module_ &m) {
m.attr("MAILBOX_ERROR_MSG_SIZE") = static_cast<int>(MAILBOX_ERROR_MSG_SIZE);
m.attr("MAX_RING_DEPTH") = static_cast<int32_t>(MAX_RING_DEPTH);
m.attr("MAX_SCOPE_DEPTH") = static_cast<int32_t>(MAX_SCOPE_DEPTH);

// --- ChipBootstrapChannel ---
m.attr("CHIP_BOOTSTRAP_MAILBOX_SIZE") = static_cast<int>(CHIP_BOOTSTRAP_MAILBOX_SIZE);

nb::enum_<ChipBootstrapMailboxState>(m, "ChipBootstrapMailboxState")
.value("IDLE", ChipBootstrapMailboxState::IDLE)
.value("SUCCESS", ChipBootstrapMailboxState::SUCCESS)
.value("ERROR", ChipBootstrapMailboxState::ERROR);

nb::class_<ChipBootstrapChannel>(m, "ChipBootstrapChannel")
.def(
"__init__",
[](ChipBootstrapChannel *self, uint64_t mailbox_ptr, size_t max_buffer_count) {
new (self) ChipBootstrapChannel(reinterpret_cast<void *>(mailbox_ptr), max_buffer_count);
},
nb::arg("mailbox_ptr"), nb::arg("max_buffer_count")
)
.def("reset", &ChipBootstrapChannel::reset)
.def(
"write_success",
[](ChipBootstrapChannel &self, uint64_t device_ctx, uint64_t local_window_base, uint64_t actual_window_size,
const std::vector<uint64_t> &buffer_ptrs) {
self.write_success(device_ctx, local_window_base, actual_window_size, buffer_ptrs);
},
nb::arg("device_ctx"), nb::arg("local_window_base"), nb::arg("actual_window_size"), nb::arg("buffer_ptrs")
)
.def(
"write_error",
[](ChipBootstrapChannel &self, int32_t error_code, const std::string &message) {
self.write_error(error_code, message);
},
nb::arg("error_code"), nb::arg("message")
)
.def_prop_ro("state", &ChipBootstrapChannel::state)
.def_prop_ro("error_code", &ChipBootstrapChannel::error_code)
.def_prop_ro("device_ctx", &ChipBootstrapChannel::device_ctx)
.def_prop_ro("local_window_base", &ChipBootstrapChannel::local_window_base)
.def_prop_ro("actual_window_size", &ChipBootstrapChannel::actual_window_size)
.def_prop_ro("buffer_ptrs", &ChipBootstrapChannel::buffer_ptrs)
.def_prop_ro("error_message", &ChipBootstrapChannel::error_message);
}
164 changes: 164 additions & 0 deletions src/common/hierarchical/chip_bootstrap_channel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*
* Copyright (c) PyPTO Contributors.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
* -----------------------------------------------------------------------------------------------------------
*/

#include "chip_bootstrap_channel.h"

#include <cstring>
#include <stdexcept>

// =============================================================================
// Internal helpers
// =============================================================================

namespace {

void write_state(void *mailbox, ChipBootstrapMailboxState s) {
auto *ptr = reinterpret_cast<volatile int32_t *>(static_cast<char *>(mailbox) + CHIP_BOOTSTRAP_OFF_STATE);
int32_t v = static_cast<int32_t>(s);
#if defined(__aarch64__)
__asm__ volatile("stlr %w0, [%1]" : : "r"(v), "r"(ptr) : "memory");
#elif defined(__x86_64__)
__asm__ volatile("" ::: "memory");
*ptr = v;
#else
__atomic_store(ptr, &v, __ATOMIC_RELEASE);
#endif
}

ChipBootstrapMailboxState read_state(void *mailbox) {
auto *ptr = reinterpret_cast<volatile int32_t *>(static_cast<char *>(mailbox) + CHIP_BOOTSTRAP_OFF_STATE);
int32_t v;
#if defined(__aarch64__)
__asm__ volatile("ldar %w0, [%1]" : "=r"(v) : "r"(ptr) : "memory");
#elif defined(__x86_64__)
v = *ptr;
__asm__ volatile("" ::: "memory");
#else
__atomic_load(ptr, &v, __ATOMIC_ACQUIRE);
#endif
return static_cast<ChipBootstrapMailboxState>(v);
}

} // namespace

// =============================================================================
// ChipBootstrapChannel
// =============================================================================

ChipBootstrapChannel::ChipBootstrapChannel(void *mailbox, size_t max_buffer_count) :
mailbox_(mailbox),
max_buffer_count_(max_buffer_count) {
if (mailbox_ == nullptr) {
throw std::invalid_argument("mailbox must not be null");
}
if (max_buffer_count_ > CHIP_BOOTSTRAP_PTR_CAPACITY) {
throw std::invalid_argument("max_buffer_count exceeds CHIP_BOOTSTRAP_PTR_CAPACITY");
}
}
Comment thread
ChaoWao marked this conversation as resolved.

void ChipBootstrapChannel::reset() {
std::memset(mailbox_, 0, CHIP_BOOTSTRAP_MAILBOX_SIZE);
write_state(mailbox_, ChipBootstrapMailboxState::IDLE);
}

void ChipBootstrapChannel::write_success(
uint64_t device_ctx, uint64_t local_window_base, uint64_t actual_window_size,
const std::vector<uint64_t> &buffer_ptrs
) {
if (buffer_ptrs.size() > max_buffer_count_) {
throw std::invalid_argument("buffer_ptrs exceeds max_buffer_count");
}

auto *base = static_cast<char *>(mailbox_);

int32_t count = static_cast<int32_t>(buffer_ptrs.size());
std::memcpy(base + CHIP_BOOTSTRAP_OFF_BUFFER_COUNT, &count, sizeof(count));
std::memcpy(base + CHIP_BOOTSTRAP_OFF_DEVICE_CTX, &device_ctx, sizeof(device_ctx));
std::memcpy(base + CHIP_BOOTSTRAP_OFF_LOCAL_WINDOW_BASE, &local_window_base, sizeof(local_window_base));
std::memcpy(base + CHIP_BOOTSTRAP_OFF_ACTUAL_WINDOW_SIZE, &actual_window_size, sizeof(actual_window_size));

if (!buffer_ptrs.empty()) {
std::memcpy(base + CHIP_BOOTSTRAP_OFF_BUFFER_PTRS, buffer_ptrs.data(), buffer_ptrs.size() * sizeof(uint64_t));
}

write_state(mailbox_, ChipBootstrapMailboxState::SUCCESS);
}

void ChipBootstrapChannel::write_error(int32_t error_code, const std::string &message) {
auto *base = static_cast<char *>(mailbox_);

std::memcpy(base + CHIP_BOOTSTRAP_OFF_ERROR_CODE, &error_code, sizeof(error_code));

size_t max_len = CHIP_BOOTSTRAP_ERROR_MSG_SIZE - 1;
size_t copy_len = message.size() < max_len ? message.size() : max_len;
std::memcpy(base + CHIP_BOOTSTRAP_OFF_ERROR_MSG, message.data(), copy_len);
base[CHIP_BOOTSTRAP_OFF_ERROR_MSG + copy_len] = '\0';

write_state(mailbox_, ChipBootstrapMailboxState::ERROR);
}

ChipBootstrapMailboxState ChipBootstrapChannel::state() const { return read_state(mailbox_); }

int32_t ChipBootstrapChannel::error_code() const {
auto *base = static_cast<const char *>(mailbox_);
int32_t v;
std::memcpy(&v, base + CHIP_BOOTSTRAP_OFF_ERROR_CODE, sizeof(v));
return v;
}

uint64_t ChipBootstrapChannel::device_ctx() const {
auto *base = static_cast<const char *>(mailbox_);
uint64_t v;
std::memcpy(&v, base + CHIP_BOOTSTRAP_OFF_DEVICE_CTX, sizeof(v));
return v;
}

uint64_t ChipBootstrapChannel::local_window_base() const {
auto *base = static_cast<const char *>(mailbox_);
uint64_t v;
std::memcpy(&v, base + CHIP_BOOTSTRAP_OFF_LOCAL_WINDOW_BASE, sizeof(v));
return v;
}

uint64_t ChipBootstrapChannel::actual_window_size() const {
auto *base = static_cast<const char *>(mailbox_);
uint64_t v;
std::memcpy(&v, base + CHIP_BOOTSTRAP_OFF_ACTUAL_WINDOW_SIZE, sizeof(v));
return v;
}

std::vector<uint64_t> ChipBootstrapChannel::buffer_ptrs() const {
auto *base = static_cast<const char *>(mailbox_);
int32_t raw_count;
std::memcpy(&raw_count, base + CHIP_BOOTSTRAP_OFF_BUFFER_COUNT, sizeof(raw_count));

// Ctor guarantees max_buffer_count_ <= CHIP_BOOTSTRAP_PTR_CAPACITY, so clamping
// count against max_buffer_count_ alone is sufficient to keep the read bounded.
size_t count =
raw_count <= 0 ?
0 :
(static_cast<size_t>(raw_count) < max_buffer_count_ ? static_cast<size_t>(raw_count) : max_buffer_count_);

std::vector<uint64_t> ptrs(count);
if (count > 0) {
std::memcpy(ptrs.data(), base + CHIP_BOOTSTRAP_OFF_BUFFER_PTRS, count * sizeof(uint64_t));
}
return ptrs;
}
Comment thread
ChaoWao marked this conversation as resolved.

std::string ChipBootstrapChannel::error_message() const {
auto *base = static_cast<const char *>(mailbox_);
const char *msg_ptr = base + CHIP_BOOTSTRAP_OFF_ERROR_MSG;
// Bound the read against the layout size so a missing null-terminator in
// shared memory (corrupt producer, premature read) can't walk off the page.
size_t len = strnlen(msg_ptr, CHIP_BOOTSTRAP_ERROR_MSG_SIZE);
return std::string(msg_ptr, len);
}
Comment thread
ChaoWao marked this conversation as resolved.
81 changes: 81 additions & 0 deletions src/common/hierarchical/chip_bootstrap_channel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright (c) PyPTO Contributors.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
* -----------------------------------------------------------------------------------------------------------
*/

/**
* ChipBootstrapChannel — one-shot cross-process mailbox for per-chip bootstrap.
*
* Lifecycle: parent allocates a CHIP_BOOTSTRAP_MAILBOX_SIZE shared-memory region,
* child writes SUCCESS/ERROR once, parent polls state() until done.
* Not a general-purpose mailbox — independent of the task-mailbox protocol.
*/

#pragma once

#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>

static constexpr size_t CHIP_BOOTSTRAP_MAILBOX_SIZE = 4096;
static constexpr size_t CHIP_BOOTSTRAP_HEADER_SIZE = 64;
static constexpr size_t CHIP_BOOTSTRAP_ERROR_MSG_SIZE = 1024;
static constexpr size_t CHIP_BOOTSTRAP_PTR_CAPACITY =
(CHIP_BOOTSTRAP_MAILBOX_SIZE - CHIP_BOOTSTRAP_HEADER_SIZE - CHIP_BOOTSTRAP_ERROR_MSG_SIZE) / sizeof(uint64_t);

// Fixed offsets within the mailbox region.
static constexpr ptrdiff_t CHIP_BOOTSTRAP_OFF_STATE = 0;
static constexpr ptrdiff_t CHIP_BOOTSTRAP_OFF_ERROR_CODE = 4;
static constexpr ptrdiff_t CHIP_BOOTSTRAP_OFF_BUFFER_COUNT = 8;
// 4 bytes implicit padding for uint64 alignment
static constexpr ptrdiff_t CHIP_BOOTSTRAP_OFF_DEVICE_CTX = 16;
static constexpr ptrdiff_t CHIP_BOOTSTRAP_OFF_LOCAL_WINDOW_BASE = 24;
static constexpr ptrdiff_t CHIP_BOOTSTRAP_OFF_ACTUAL_WINDOW_SIZE = 32;
static constexpr ptrdiff_t CHIP_BOOTSTRAP_OFF_BUFFER_PTRS = 64;
static constexpr ptrdiff_t CHIP_BOOTSTRAP_OFF_ERROR_MSG =
CHIP_BOOTSTRAP_OFF_BUFFER_PTRS + static_cast<ptrdiff_t>(CHIP_BOOTSTRAP_PTR_CAPACITY * sizeof(uint64_t));

static_assert(
CHIP_BOOTSTRAP_OFF_ERROR_MSG + static_cast<ptrdiff_t>(CHIP_BOOTSTRAP_ERROR_MSG_SIZE) ==
static_cast<ptrdiff_t>(CHIP_BOOTSTRAP_MAILBOX_SIZE),
"mailbox layout must sum to 4096"
);

enum class ChipBootstrapMailboxState : int32_t {
IDLE = 0,
SUCCESS = 1,
ERROR = 2,
};

class ChipBootstrapChannel {
public:
ChipBootstrapChannel(void *mailbox, size_t max_buffer_count);

// Write side (child process).
void reset();
void write_success(
uint64_t device_ctx, uint64_t local_window_base, uint64_t actual_window_size,
const std::vector<uint64_t> &buffer_ptrs
);
void write_error(int32_t error_code, const std::string &message);

// Read side (parent process).
ChipBootstrapMailboxState state() const;
int32_t error_code() const;
uint64_t device_ctx() const;
uint64_t local_window_base() const;
uint64_t actual_window_size() const;
std::vector<uint64_t> buffer_ptrs() const;
std::string error_message() const;

private:
void *mailbox_;
size_t max_buffer_count_;
};
Loading
Loading