vyre-runtime 0.6.3

Persistent megakernel + io_uring zero-copy streaming runtime for vyre - GPU as VIR0 bytecode interpreter
Documentation
use super::*;

#[test]
fn encode_work_items_ring_into_publishes_contiguous_slots() {
    let items = [
        MegakernelWorkItem {
            op_handle: protocol::opcode::STORE_U32,
            input_handle: 10,
            output_handle: 20,
            param: 30,
        },
        MegakernelWorkItem {
            op_handle: protocol::opcode::ATOMIC_ADD,
            input_handle: 40,
            output_handle: 50,
            param: 60,
        },
    ];
    let mut ring = vec![0xAA; 4096];

    Megakernel::encode_work_items_ring_into(4, 7, &items, &mut ring).unwrap();

    assert_eq!(read_word(&ring, 0, STATUS_WORD as usize), slot::PUBLISHED);
    assert_eq!(
        read_word(&ring, 0, OPCODE_WORD as usize),
        protocol::opcode::STORE_U32
    );
    assert_eq!(read_word(&ring, 0, TENANT_WORD as usize), 7);
    assert_eq!(
        read_word(&ring, 0, PRIORITY_WORD as usize),
        scheduler::priority::NORMAL
    );
    assert_eq!(read_word(&ring, 0, ARG0_WORD as usize), 10);
    assert_eq!(read_word(&ring, 0, ARG0_WORD as usize + 1), 20);
    assert_eq!(read_word(&ring, 0, ARG0_WORD as usize + 2), 30);
    assert_eq!(read_word(&ring, 1, STATUS_WORD as usize), slot::PUBLISHED);
    assert_eq!(
        read_word(&ring, 1, OPCODE_WORD as usize),
        protocol::opcode::ATOMIC_ADD
    );
    assert_eq!(read_word(&ring, 1, ARG0_WORD as usize), 40);
    assert_eq!(read_word(&ring, 1, ARG0_WORD as usize + 1), 50);
    assert_eq!(read_word(&ring, 1, ARG0_WORD as usize + 2), 60);
    assert_eq!(read_word(&ring, 2, STATUS_WORD as usize), slot::EMPTY);
}

#[test]
fn encode_work_items_ring_words_into_matches_byte_encoder() {
    let items = [
        MegakernelWorkItem {
            op_handle: protocol::opcode::STORE_U32,
            input_handle: 10,
            output_handle: 20,
            param: 30,
        },
        MegakernelWorkItem {
            op_handle: protocol::opcode::ATOMIC_ADD,
            input_handle: 40,
            output_handle: 50,
            param: 60,
        },
    ];
    let mut bytes = Vec::new();
    let mut words = Vec::new();

    Megakernel::encode_work_items_ring_into(4, 7, &items, &mut bytes).unwrap();
    Megakernel::encode_work_items_ring_words_into(4, 7, &items, &mut words).unwrap();

    assert_eq!(bytemuck::cast_slice::<u32, u8>(&words), bytes.as_slice());
}

#[test]
fn encode_work_items_ring_words_into_reuses_buffer_by_clearing_status_words() {
    let first = [
        MegakernelWorkItem {
            op_handle: protocol::opcode::STORE_U32,
            input_handle: 10,
            output_handle: 20,
            param: 30,
        },
        MegakernelWorkItem {
            op_handle: protocol::opcode::ATOMIC_ADD,
            input_handle: 40,
            output_handle: 50,
            param: 60,
        },
    ];
    let second = [MegakernelWorkItem {
        op_handle: protocol::opcode::STORE_U32,
        input_handle: 70,
        output_handle: 80,
        param: 90,
    }];
    let mut words = Vec::new();

    Megakernel::encode_work_items_ring_words_into(4, 7, &first, &mut words).unwrap();
    Megakernel::encode_work_items_ring_words_into(4, 7, &second, &mut words).unwrap();

    assert_eq!(
        read_word_words(&words, 0, STATUS_WORD as usize),
        slot::PUBLISHED
    );
    assert_eq!(read_word_words(&words, 0, ARG0_WORD as usize), 70);
    assert_eq!(read_word_words(&words, 0, ARG0_WORD as usize + 1), 80);
    assert_eq!(read_word_words(&words, 0, ARG0_WORD as usize + 2), 90);
    assert_eq!(
        read_word_words(&words, 1, STATUS_WORD as usize),
        slot::EMPTY
    );
    assert_eq!(
        read_word_words(&words, 2, STATUS_WORD as usize),
        slot::EMPTY
    );
    assert_eq!(
        read_word_words(&words, 3, STATUS_WORD as usize),
        slot::EMPTY
    );
}

#[test]
fn publish_work_items_updates_window_without_resetting_unrelated_slots() {
    let mut ring = Megakernel::encode_empty_ring(4).unwrap();
    write_word(&mut ring, 0, ARG0_WORD as usize, 0xDEAD_BEEF);
    write_word(&mut ring, 3, ARG0_WORD as usize, 0xABCD_EF01);
    let items = [
        MegakernelWorkItem {
            op_handle: protocol::opcode::STORE_U32,
            input_handle: 10,
            output_handle: 20,
            param: 30,
        },
        MegakernelWorkItem {
            op_handle: protocol::opcode::ATOMIC_ADD,
            input_handle: 40,
            output_handle: 50,
            param: 60,
        },
    ];

    let published = Megakernel::publish_work_items(&mut ring, 1, 7, &items).unwrap();

    assert_eq!(published, 2);
    assert_eq!(read_word(&ring, 0, ARG0_WORD as usize), 0xDEAD_BEEF);
    assert_eq!(read_word(&ring, 3, ARG0_WORD as usize), 0xABCD_EF01);
    assert_eq!(read_word(&ring, 1, STATUS_WORD as usize), slot::PUBLISHED);
    assert_eq!(
        read_word(&ring, 1, OPCODE_WORD as usize),
        protocol::opcode::STORE_U32
    );
    assert_eq!(read_word(&ring, 1, TENANT_WORD as usize), 7);
    assert_eq!(read_word(&ring, 1, ARG0_WORD as usize), 10);
    assert_eq!(read_word(&ring, 1, ARG0_WORD as usize + 1), 20);
    assert_eq!(read_word(&ring, 1, ARG0_WORD as usize + 2), 30);
    assert_eq!(read_word(&ring, 2, STATUS_WORD as usize), slot::PUBLISHED);
    assert_eq!(
        read_word(&ring, 2, OPCODE_WORD as usize),
        protocol::opcode::ATOMIC_ADD
    );
    assert_eq!(read_word(&ring, 2, ARG0_WORD as usize), 40);
    assert_eq!(read_word(&ring, 2, ARG0_WORD as usize + 1), 50);
    assert_eq!(read_word(&ring, 2, ARG0_WORD as usize + 2), 60);
}

#[test]
fn publish_work_items_rejects_inflight_window_without_mutating() {
    let mut ring = Megakernel::encode_empty_ring(4).unwrap();
    write_word(&mut ring, 1, STATUS_WORD as usize, slot::CLAIMED);
    let before = ring.clone();
    let items = [MegakernelWorkItem {
        op_handle: protocol::opcode::STORE_U32,
        input_handle: 10,
        output_handle: 20,
        param: 30,
    }];

    let error = Megakernel::publish_work_items(&mut ring, 1, 7, &items)
        .expect_err("in-flight target slots must be rejected before mutation");

    assert!(error.to_string().contains("not publishable"));
    assert_eq!(ring, before);
}

#[test]
fn encode_work_items_ring_into_rejects_oversized_queue_without_mutating() {
    let items = [
        MegakernelWorkItem {
            op_handle: protocol::opcode::STORE_U32,
            input_handle: 1,
            output_handle: 2,
            param: 3,
        },
        MegakernelWorkItem {
            op_handle: protocol::opcode::STORE_U32,
            input_handle: 4,
            output_handle: 5,
            param: 6,
        },
    ];
    let mut ring = vec![0xAA; 8];

    let result = Megakernel::encode_work_items_ring_into(1, 0, &items, &mut ring);

    assert!(result.is_err(), "oversized queue must be rejected");
    assert_eq!(ring, vec![0xAA; 8], "rejection must not mutate ring");
}

#[test]
fn encode_work_items_ring_into_rejects_bad_opcode_without_mutating() {
    let items = [MegakernelWorkItem {
        op_handle: protocol::opcode::RESERVED_MAX_RANGE_MIN,
        input_handle: 1,
        output_handle: 2,
        param: 3,
    }];
    let mut ring = vec![0xAA; 8];

    let result = Megakernel::encode_work_items_ring_into(1, 0, &items, &mut ring);

    assert!(result.is_err(), "invalid opcode must be rejected");
    assert_eq!(ring, vec![0xAA; 8], "rejection must not mutate ring");
}