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]
members = [
"fake-vec-core",
"kata-ml-component",
"kata-ml-coordinator",
"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::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(&sections);
MlCore::set_wmmu(&sections);
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);
}

View File

@@ -7,4 +7,3 @@ edition = "2021"
[dependencies]
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]
#![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" {

View File

@@ -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]
}

View File

@@ -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()) }
}