mirror of
https://github.com/AmbiML/sparrow-kata-full.git
synced 2025-09-25 14:49:13 +00:00
Merge "Refactor kata-vec-core and add fake-vec-core"
GitOrigin-RevId: 96f07ab9323932ee3b06da58367a5b95a4d7718b
This commit is contained in:
committed by
Sam Leffler
parent
3992cc998a
commit
8800dc4a96
@@ -3,6 +3,7 @@ cargo-features = ["edition2021"]
|
||||
[workspace]
|
||||
|
||||
members = [
|
||||
"fake-vec-core",
|
||||
"kata-ml-component",
|
||||
"kata-ml-coordinator",
|
||||
"kata-ml-interface",
|
||||
|
@@ -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" }
|
||||
|
@@ -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
|
||||
}
|
@@ -7,11 +7,10 @@ extern crate alloc;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use kata_ml_interface::MlCoordError;
|
||||
use kata_ml_interface::MlCoreInterface;
|
||||
use kata_os_common::cspace_slot::CSpaceSlot;
|
||||
use kata_security_interface::*;
|
||||
use kata_timer_interface::*;
|
||||
use kata_vec_core::MlCore;
|
||||
use kata_vec_core as MlCore;
|
||||
use log::{error, info, trace, warn};
|
||||
|
||||
/// 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.
|
||||
execution_queue: Vec<ModelIdx>,
|
||||
statistics: Statistics,
|
||||
ml_core: MlCore,
|
||||
}
|
||||
|
||||
// The index of a model in MLCoordinator.models
|
||||
@@ -63,13 +61,12 @@ impl MLCoordinator {
|
||||
models: [INIT_NONE; MAX_MODELS],
|
||||
execution_queue: Vec::new(),
|
||||
statistics: Statistics{load_failures: 0, already_queued: 0},
|
||||
ml_core: MlCore {},
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize the vector core.
|
||||
pub fn init(&mut self) {
|
||||
self.ml_core.enable_interrupts(true);
|
||||
MlCore::enable_interrupts(true);
|
||||
self.execution_queue.reserve(MAX_MODELS);
|
||||
}
|
||||
|
||||
@@ -95,7 +92,7 @@ impl MLCoordinator {
|
||||
let container_slot = CSpaceSlot::new();
|
||||
match kata_security_load_model(&model.bundle_id, &model.model_id, &container_slot) {
|
||||
Ok(model_frames) => {
|
||||
match self.ml_core.load_image(&model_frames) {
|
||||
match MlCore::load_image(&model_frames) {
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Load of {}:{} failed: {:?}",
|
||||
@@ -108,7 +105,7 @@ impl MLCoordinator {
|
||||
}
|
||||
Ok(sections) => {
|
||||
info!("Load successful.");
|
||||
self.ml_core.set_wmmu(§ions);
|
||||
MlCore::set_wmmu(§ions);
|
||||
self.loaded_model = Some(model_idx);
|
||||
Ok(())
|
||||
}
|
||||
@@ -134,7 +131,7 @@ impl MLCoordinator {
|
||||
// It's very unlikely for load errors to be transient, it should
|
||||
// only happen in the case of a mal-formed model.
|
||||
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);
|
||||
}
|
||||
|
||||
|
@@ -7,4 +7,3 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
cstr_core = { version = "0.2.3", default-features = false }
|
||||
kata-memory-interface = { path = "../../MemoryManager/kata-memory-interface" }
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#![no_std]
|
||||
#![allow(dead_code)]
|
||||
use cstr_core::CString;
|
||||
use kata_memory_interface::ObjDescBundle;
|
||||
|
||||
/// The Vector Core uses a Windowed MMU (go/sparrow-wmmu) in order to prevent
|
||||
/// 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]
|
||||
pub fn kata_mlcoord_oneshot(bundle_id: &str, model_id: &str) -> Result<(), MlCoordError> {
|
||||
extern "C" {
|
||||
|
@@ -8,7 +8,7 @@ mod vc_top;
|
||||
use core::mem::size_of;
|
||||
use core::slice;
|
||||
use kata_memory_interface::ObjDescBundle;
|
||||
use kata_ml_interface::{MlCoreInterface, ModelSections, Window};
|
||||
use kata_ml_interface::{ModelSections, Window};
|
||||
use kata_proc_interface::BundleImage;
|
||||
|
||||
use io::Read;
|
||||
@@ -24,7 +24,6 @@ const ITCM_PADDR: usize = 0x32000000;
|
||||
const DTCM_SIZE: usize = 0x1000000;
|
||||
const DTCM_PADDR: usize = 0x34000000;
|
||||
|
||||
// TODO(jesionowski): ITCM / DTCM will eventually be merged into a single memory.
|
||||
extern "C" {
|
||||
static itcm: *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] {
|
||||
unsafe { slice::from_raw_parts_mut(dtcm, DTCM_SIZE / size_of::<u32>()) }
|
||||
pub fn enable_interrupts(enable: bool) {
|
||||
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 {}
|
||||
|
||||
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) {
|
||||
pub fn set_wmmu(sections: &ModelSections) {
|
||||
// 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:
|
||||
// 0x400000 is 23 bits vs. 0x3FFFFF 22 bits.
|
||||
@@ -76,16 +59,7 @@ impl MlCoreInterface for MlCore {
|
||||
vc_top::set_dmmu_window_permission(0, vc_top::Permission::ReadAndWrite);
|
||||
}
|
||||
|
||||
fn enable_interrupts(&mut self, enable: bool) {
|
||||
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) {
|
||||
pub fn run() {
|
||||
let ctrl = vc_top::Ctrl::new()
|
||||
.with_freeze(false)
|
||||
.with_vc_reset(false)
|
||||
@@ -94,7 +68,7 @@ impl MlCoreInterface for MlCore {
|
||||
}
|
||||
|
||||
// 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 itcm_found = false;
|
||||
let mut dtcm_found = false;
|
||||
@@ -152,39 +126,62 @@ impl MlCoreInterface for MlCore {
|
||||
})
|
||||
}
|
||||
|
||||
// TODO(jesionowski): Read these from CSRs when available.
|
||||
fn get_return_code() -> u32 {
|
||||
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() {
|
||||
pub fn clear_host_req() {
|
||||
let mut intr_state = vc_top::get_intr_state();
|
||||
intr_state.set_host_req(true);
|
||||
vc_top::set_intr_state(intr_state);
|
||||
}
|
||||
|
||||
fn clear_finish() {
|
||||
pub fn clear_finish() {
|
||||
let mut intr_state = vc_top::get_intr_state();
|
||||
intr_state.set_finish(true);
|
||||
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();
|
||||
intr_state.set_instruction_fault(true);
|
||||
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();
|
||||
intr_state.set_data_fault(true);
|
||||
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]
|
||||
}
|
||||
|
@@ -1,9 +1,14 @@
|
||||
// Auto-generated hardware structs from vc_top.hjson
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
// Setters and getters for the Vector Core CSRs.
|
||||
|
||||
use core::ptr;
|
||||
use modular_bitfield::prelude::*;
|
||||
|
||||
extern "C" {
|
||||
static csr: *mut [u32; 9];
|
||||
}
|
||||
|
||||
#[bitfield]
|
||||
pub struct IntrState {
|
||||
pub host_req: bool,
|
||||
@@ -85,10 +90,6 @@ pub struct InitStatus {
|
||||
pub _unused0: B30,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
static csr: *mut [u32; 9];
|
||||
}
|
||||
|
||||
pub fn get_intr_state() -> IntrState {
|
||||
unsafe { IntrState::from_bytes(ptr::read_volatile(csr)[0].to_ne_bytes()) }
|
||||
}
|
||||
|
Reference in New Issue
Block a user