Merge "Refactor kata-vec-core and add fake-vec-core"

GitOrigin-RevId: 96f07ab9323932ee3b06da58367a5b95a4d7718b
This commit is contained in:
Adam Jesionowski
2022-06-14 18:53:27 +00:00
committed by Sam Leffler
parent 3992cc998a
commit 8800dc4a96
8 changed files with 190 additions and 161 deletions

View File

@@ -3,6 +3,7 @@ cargo-features = ["edition2021"]
[workspace] [workspace]
members = [ members = [
"fake-vec-core",
"kata-ml-component", "kata-ml-component",
"kata-ml-coordinator", "kata-ml-coordinator",
"kata-ml-interface", "kata-ml-interface",

View File

@@ -0,0 +1,11 @@
cargo-features = ["edition2021"]
[package]
name = "fake-vec-core"
version = "0.1.0"
edition = "2021"
[dependencies]
kata-memory-interface = { path = "../../MemoryManager/kata-memory-interface" }
kata-ml-interface = { path = "../kata-ml-interface" }

View File

@@ -0,0 +1,38 @@
#![no_std]
// fake-vec-core is a stubbed out version of kata-vec-core.
use kata_memory_interface::ObjDescBundle;
use kata_ml_interface::{ModelSections, Window};
pub fn enable_interrupts(_enable: bool) {}
pub fn set_wmmu(_sections: &ModelSections) {}
// NB: this function will be moved out of *-vec-core shortly.
pub fn load_image(_frames: &ObjDescBundle) -> Result<ModelSections, &'static str> {
Ok(ModelSections {
instructions: Window { addr: 0, size: 0 },
data: Window { addr: 0, size: 0 },
})
}
pub fn run() {}
pub fn clear_host_req() {}
pub fn clear_finish() {}
pub fn clear_instruction_fault() {}
pub fn clear_data_fault() {}
pub fn clear_tcm() {}
pub fn get_return_code() -> u32 {
0
}
pub fn get_fault_register() -> u32 {
0
}

View File

@@ -7,11 +7,10 @@ extern crate alloc;
use alloc::string::String; use alloc::string::String;
use alloc::vec::Vec; use alloc::vec::Vec;
use kata_ml_interface::MlCoordError; use kata_ml_interface::MlCoordError;
use kata_ml_interface::MlCoreInterface;
use kata_os_common::cspace_slot::CSpaceSlot; use kata_os_common::cspace_slot::CSpaceSlot;
use kata_security_interface::*; use kata_security_interface::*;
use kata_timer_interface::*; use kata_timer_interface::*;
use kata_vec_core::MlCore; use kata_vec_core as MlCore;
use log::{error, info, trace, warn}; use log::{error, info, trace, warn};
/// The maximum number of models that the MLCoordinator can handle, bounded by /// The maximum number of models that the MLCoordinator can handle, bounded by
@@ -46,7 +45,6 @@ pub struct MLCoordinator {
/// core, once the currently running model has finished. /// core, once the currently running model has finished.
execution_queue: Vec<ModelIdx>, execution_queue: Vec<ModelIdx>,
statistics: Statistics, statistics: Statistics,
ml_core: MlCore,
} }
// The index of a model in MLCoordinator.models // The index of a model in MLCoordinator.models
@@ -63,13 +61,12 @@ impl MLCoordinator {
models: [INIT_NONE; MAX_MODELS], models: [INIT_NONE; MAX_MODELS],
execution_queue: Vec::new(), execution_queue: Vec::new(),
statistics: Statistics{load_failures: 0, already_queued: 0}, statistics: Statistics{load_failures: 0, already_queued: 0},
ml_core: MlCore {},
} }
} }
/// Initialize the vector core. /// Initialize the vector core.
pub fn init(&mut self) { pub fn init(&mut self) {
self.ml_core.enable_interrupts(true); MlCore::enable_interrupts(true);
self.execution_queue.reserve(MAX_MODELS); self.execution_queue.reserve(MAX_MODELS);
} }
@@ -95,7 +92,7 @@ impl MLCoordinator {
let container_slot = CSpaceSlot::new(); let container_slot = CSpaceSlot::new();
match kata_security_load_model(&model.bundle_id, &model.model_id, &container_slot) { match kata_security_load_model(&model.bundle_id, &model.model_id, &container_slot) {
Ok(model_frames) => { Ok(model_frames) => {
match self.ml_core.load_image(&model_frames) { match MlCore::load_image(&model_frames) {
Err(e) => { Err(e) => {
error!( error!(
"Load of {}:{} failed: {:?}", "Load of {}:{} failed: {:?}",
@@ -108,7 +105,7 @@ impl MLCoordinator {
} }
Ok(sections) => { Ok(sections) => {
info!("Load successful."); info!("Load successful.");
self.ml_core.set_wmmu(&sections); MlCore::set_wmmu(&sections);
self.loaded_model = Some(model_idx); self.loaded_model = Some(model_idx);
Ok(()) Ok(())
} }
@@ -134,7 +131,7 @@ impl MLCoordinator {
// It's very unlikely for load errors to be transient, it should // It's very unlikely for load errors to be transient, it should
// only happen in the case of a mal-formed model. // only happen in the case of a mal-formed model.
self.load_model(next_idx)?; self.load_model(next_idx)?;
self.ml_core.run(); // Unhalt, start at default PC. MlCore::run(); // Unhalt, start at default PC.
self.running_model = Some(next_idx); self.running_model = Some(next_idx);
} }

View File

@@ -7,4 +7,3 @@ edition = "2021"
[dependencies] [dependencies]
cstr_core = { version = "0.2.3", default-features = false } cstr_core = { version = "0.2.3", default-features = false }
kata-memory-interface = { path = "../../MemoryManager/kata-memory-interface" }

View File

@@ -1,7 +1,6 @@
#![no_std] #![no_std]
#![allow(dead_code)] #![allow(dead_code)]
use cstr_core::CString; use cstr_core::CString;
use kata_memory_interface::ObjDescBundle;
/// The Vector Core uses a Windowed MMU (go/sparrow-wmmu) in order to prevent /// The Vector Core uses a Windowed MMU (go/sparrow-wmmu) in order to prevent
/// models from interferring with each other. Before executing a model, /// models from interferring with each other. Before executing a model,
@@ -41,20 +40,6 @@ impl From<MlCoordError> for Result<(), MlCoordError> {
} }
} }
/// Abstraction layer over the hardware vector core.
pub trait MlCoreInterface {
fn set_wmmu(&mut self, sections: &ModelSections);
fn enable_interrupts(&mut self, enabled: bool);
fn run(&mut self);
fn load_image(&mut self, frames: &ObjDescBundle) -> Result<ModelSections, &'static str>;
fn get_return_code() -> u32;
fn get_fault_register() -> u32;
fn clear_host_req();
fn clear_finish();
fn clear_instruction_fault();
fn clear_data_fault();
}
#[inline] #[inline]
pub fn kata_mlcoord_oneshot(bundle_id: &str, model_id: &str) -> Result<(), MlCoordError> { pub fn kata_mlcoord_oneshot(bundle_id: &str, model_id: &str) -> Result<(), MlCoordError> {
extern "C" { extern "C" {

View File

@@ -8,7 +8,7 @@ mod vc_top;
use core::mem::size_of; use core::mem::size_of;
use core::slice; use core::slice;
use kata_memory_interface::ObjDescBundle; use kata_memory_interface::ObjDescBundle;
use kata_ml_interface::{MlCoreInterface, ModelSections, Window}; use kata_ml_interface::{ModelSections, Window};
use kata_proc_interface::BundleImage; use kata_proc_interface::BundleImage;
use io::Read; use io::Read;
@@ -24,7 +24,6 @@ const ITCM_PADDR: usize = 0x32000000;
const DTCM_SIZE: usize = 0x1000000; const DTCM_SIZE: usize = 0x1000000;
const DTCM_PADDR: usize = 0x34000000; const DTCM_PADDR: usize = 0x34000000;
// TODO(jesionowski): ITCM / DTCM will eventually be merged into a single memory.
extern "C" { extern "C" {
static itcm: *mut u32; static itcm: *mut u32;
static dtcm: *mut u32; static dtcm: *mut u32;
@@ -38,32 +37,16 @@ fn round_up(a: usize, b: usize) -> usize {
} }
} }
fn get_dtcm_slice() -> &'static mut [u32] { pub fn enable_interrupts(enable: bool) {
unsafe { slice::from_raw_parts_mut(dtcm, DTCM_SIZE / size_of::<u32>()) } let intr_enable = vc_top::IntrEnable::new()
.with_host_req(enable)
.with_finish(enable)
.with_instruction_fault(enable)
.with_data_fault(enable);
vc_top::set_intr_enable(intr_enable);
} }
pub struct MlCore {} pub fn set_wmmu(sections: &ModelSections) {
fn clear_section(start: u32, end: u32, is_itcm: bool) {
let init_start = vc_top::InitStart::new()
.with_address(start)
.with_imem_dmem_sel(is_itcm);
vc_top::set_init_start(init_start);
let init_end = vc_top::InitEnd::new().with_address(end).with_valid(true);
vc_top::set_init_end(init_end);
while !vc_top::get_init_status().init_done() {}
}
fn clear_tcm() {
clear_section(0, ITCM_SIZE as u32, true);
// TODO(jesionowski): Enable when DTCM_SIZE fits into INIT_END.
// clear_section(0, DTCM_SIZE as u32, false);
}
impl MlCoreInterface for MlCore {
fn set_wmmu(&mut self, sections: &ModelSections) {
// The length of the window is not the size of the window, but rather // The length of the window is not the size of the window, but rather
// the last address of the window. This saves us a bit in hardware: // the last address of the window. This saves us a bit in hardware:
// 0x400000 is 23 bits vs. 0x3FFFFF 22 bits. // 0x400000 is 23 bits vs. 0x3FFFFF 22 bits.
@@ -74,27 +57,18 @@ impl MlCoreInterface for MlCore {
vc_top::set_dmmu_window_offset(0, sections.data.addr); vc_top::set_dmmu_window_offset(0, sections.data.addr);
vc_top::set_dmmu_window_length(0, sections.data.size - 1); vc_top::set_dmmu_window_length(0, sections.data.size - 1);
vc_top::set_dmmu_window_permission(0, vc_top::Permission::ReadAndWrite); vc_top::set_dmmu_window_permission(0, vc_top::Permission::ReadAndWrite);
} }
fn enable_interrupts(&mut self, enable: bool) { pub fn run() {
let intr_enable = vc_top::IntrEnable::new()
.with_host_req(enable)
.with_finish(enable)
.with_instruction_fault(enable)
.with_data_fault(enable);
vc_top::set_intr_enable(intr_enable);
}
fn run(&mut self) {
let ctrl = vc_top::Ctrl::new() let ctrl = vc_top::Ctrl::new()
.with_freeze(false) .with_freeze(false)
.with_vc_reset(false) .with_vc_reset(false)
.with_pc_start(0); .with_pc_start(0);
vc_top::set_ctrl(ctrl); vc_top::set_ctrl(ctrl);
} }
// Loads the model into the TCM. // Loads the model into the TCM.
fn load_image(&mut self, frames: &ObjDescBundle) -> Result<ModelSections, &'static str> { pub fn load_image(frames: &ObjDescBundle) -> Result<ModelSections, &'static str> {
let mut image = BundleImage::new(frames); let mut image = BundleImage::new(frames);
let mut itcm_found = false; let mut itcm_found = false;
let mut dtcm_found = false; let mut dtcm_found = false;
@@ -150,41 +124,64 @@ impl MlCoreInterface for MlCore {
instructions: iwindow, instructions: iwindow,
data: dwindow, data: dwindow,
}) })
} }
// TODO(jesionowski): Read these from CSRs when available. // Interrupts are write 1 to clear.
fn get_return_code() -> u32 { pub fn clear_host_req() {
const RC_OFFSET: usize = 0x3FFFEE;
get_dtcm_slice()[RC_OFFSET]
}
fn get_fault_register() -> u32 {
const FAULT_OFFSET: usize = 0x3FFFEF;
get_dtcm_slice()[FAULT_OFFSET]
}
// Interrupts are write 1 to clear.
fn clear_host_req() {
let mut intr_state = vc_top::get_intr_state(); let mut intr_state = vc_top::get_intr_state();
intr_state.set_host_req(true); intr_state.set_host_req(true);
vc_top::set_intr_state(intr_state); vc_top::set_intr_state(intr_state);
} }
fn clear_finish() { pub fn clear_finish() {
let mut intr_state = vc_top::get_intr_state(); let mut intr_state = vc_top::get_intr_state();
intr_state.set_finish(true); intr_state.set_finish(true);
vc_top::set_intr_state(intr_state); vc_top::set_intr_state(intr_state);
} }
fn clear_instruction_fault() { pub fn clear_instruction_fault() {
let mut intr_state = vc_top::get_intr_state(); let mut intr_state = vc_top::get_intr_state();
intr_state.set_instruction_fault(true); intr_state.set_instruction_fault(true);
vc_top::set_intr_state(intr_state); vc_top::set_intr_state(intr_state);
} }
fn clear_data_fault() { pub fn clear_data_fault() {
let mut intr_state = vc_top::get_intr_state(); let mut intr_state = vc_top::get_intr_state();
intr_state.set_data_fault(true); intr_state.set_data_fault(true);
vc_top::set_intr_state(intr_state); vc_top::set_intr_state(intr_state);
} }
fn clear_section(start: u32, end: u32, is_itcm: bool) {
let init_start = vc_top::InitStart::new()
.with_address(start)
.with_imem_dmem_sel(is_itcm);
vc_top::set_init_start(init_start);
let init_end = vc_top::InitEnd::new().with_address(end).with_valid(true);
vc_top::set_init_end(init_end);
while !vc_top::get_init_status().init_done() {}
}
pub fn clear_tcm() {
clear_section(0, ITCM_SIZE as u32, true);
// TODO(jesionowski): Enable when DTCM_SIZE fits into INIT_END.
// clear_section(0, DTCM_SIZE as u32, false);
}
// TODO(jesionowski): Remove these when error handling is refactored.
// The status will be faulty iff the interrupt line is raised, and
// we won't have the fault registers on Springbok.
fn get_dtcm_slice() -> &'static mut [u32] {
unsafe { slice::from_raw_parts_mut(dtcm, DTCM_SIZE / size_of::<u32>()) }
}
pub fn get_return_code() -> u32 {
const RC_OFFSET: usize = 0x3FFFEE;
get_dtcm_slice()[RC_OFFSET]
}
pub fn get_fault_register() -> u32 {
const FAULT_OFFSET: usize = 0x3FFFEF;
get_dtcm_slice()[FAULT_OFFSET]
} }

View File

@@ -1,9 +1,14 @@
// Auto-generated hardware structs from vc_top.hjson
#![allow(unused)] #![allow(unused)]
// Setters and getters for the Vector Core CSRs.
use core::ptr; use core::ptr;
use modular_bitfield::prelude::*; use modular_bitfield::prelude::*;
extern "C" {
static csr: *mut [u32; 9];
}
#[bitfield] #[bitfield]
pub struct IntrState { pub struct IntrState {
pub host_req: bool, pub host_req: bool,
@@ -85,10 +90,6 @@ pub struct InitStatus {
pub _unused0: B30, pub _unused0: B30,
} }
extern "C" {
static csr: *mut [u32; 9];
}
pub fn get_intr_state() -> IntrState { pub fn get_intr_state() -> IntrState {
unsafe { IntrState::from_bytes(ptr::read_volatile(csr)[0].to_ne_bytes()) } unsafe { IntrState::from_bytes(ptr::read_volatile(csr)[0].to_ne_bytes()) }
} }