mirror of
https://github.com/AmbiML/sparrow-kata-full.git
synced 2025-09-25 22:59:20 +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]
|
[workspace]
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
|
"fake-vec-core",
|
||||||
"kata-ml-component",
|
"kata-ml-component",
|
||||||
"kata-ml-coordinator",
|
"kata-ml-coordinator",
|
||||||
"kata-ml-interface",
|
"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::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(§ions);
|
MlCore::set_wmmu(§ions);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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" }
|
|
||||||
|
@@ -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" {
|
||||||
|
@@ -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,11 +37,119 @@ 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) {
|
||||||
|
// 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.
|
||||||
|
vc_top::set_immu_window_offset(0, sections.instructions.addr);
|
||||||
|
vc_top::set_immu_window_length(0, sections.instructions.size - 1);
|
||||||
|
vc_top::set_immu_window_permission(0, vc_top::Permission::Read);
|
||||||
|
|
||||||
|
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_permission(0, vc_top::Permission::ReadAndWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run() {
|
||||||
|
let ctrl = vc_top::Ctrl::new()
|
||||||
|
.with_freeze(false)
|
||||||
|
.with_vc_reset(false)
|
||||||
|
.with_pc_start(0);
|
||||||
|
vc_top::set_ctrl(ctrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loads the model into the TCM.
|
||||||
|
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;
|
||||||
|
// Size of windows is filled in below.
|
||||||
|
let mut iwindow = Window {
|
||||||
|
addr: ITCM_PADDR,
|
||||||
|
size: 0,
|
||||||
|
};
|
||||||
|
let mut dwindow = Window {
|
||||||
|
addr: DTCM_PADDR,
|
||||||
|
size: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
clear_tcm();
|
||||||
|
// NB: we require both ITCM & DTCM sections and that only one
|
||||||
|
// instance of each is present
|
||||||
|
while let Some(section) = image.next_section() {
|
||||||
|
let slice = if section.vaddr == ITCM_PADDR {
|
||||||
|
if itcm_found {
|
||||||
|
return Err("dup ITCM");
|
||||||
|
}
|
||||||
|
itcm_found = true;
|
||||||
|
|
||||||
|
if section.fsize > ITCM_SIZE {
|
||||||
|
return Err("ITCM too big");
|
||||||
|
}
|
||||||
|
iwindow.size = round_up(section.msize, WMMU_PAGE_SIZE);
|
||||||
|
unsafe { slice::from_raw_parts_mut(itcm as *mut u8, ITCM_SIZE) }
|
||||||
|
} else if section.vaddr == DTCM_PADDR {
|
||||||
|
if dtcm_found {
|
||||||
|
return Err("dup DTCM");
|
||||||
|
}
|
||||||
|
dtcm_found = true;
|
||||||
|
|
||||||
|
if section.fsize > DTCM_SIZE {
|
||||||
|
return Err("DTCM section too big");
|
||||||
|
}
|
||||||
|
dwindow.size = round_up(section.msize, WMMU_PAGE_SIZE);
|
||||||
|
unsafe { slice::from_raw_parts_mut(dtcm as *mut u8, DTCM_SIZE) }
|
||||||
|
} else {
|
||||||
|
return Err("Unexpected section");
|
||||||
|
};
|
||||||
|
image
|
||||||
|
.read_exact(&mut slice[section.data_range()])
|
||||||
|
.map_err(|_| "section read error")?;
|
||||||
|
// TODO(jesionowski): Remove when clear_tcm is fully implemented.
|
||||||
|
slice[section.zero_range()].fill(0x00);
|
||||||
|
}
|
||||||
|
if !itcm_found || !dtcm_found {
|
||||||
|
return Err("Incomplete");
|
||||||
|
}
|
||||||
|
Ok(ModelSections {
|
||||||
|
instructions: iwindow,
|
||||||
|
data: dwindow,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interrupts are write 1 to clear.
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
fn clear_section(start: u32, end: u32, is_itcm: bool) {
|
||||||
let init_start = vc_top::InitStart::new()
|
let init_start = vc_top::InitStart::new()
|
||||||
@@ -56,135 +163,25 @@ fn clear_section(start: u32, end: u32, is_itcm: bool) {
|
|||||||
while !vc_top::get_init_status().init_done() {}
|
while !vc_top::get_init_status().init_done() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_tcm() {
|
pub fn clear_tcm() {
|
||||||
clear_section(0, ITCM_SIZE as u32, true);
|
clear_section(0, ITCM_SIZE as u32, true);
|
||||||
// TODO(jesionowski): Enable when DTCM_SIZE fits into INIT_END.
|
// TODO(jesionowski): Enable when DTCM_SIZE fits into INIT_END.
|
||||||
// clear_section(0, DTCM_SIZE as u32, false);
|
// clear_section(0, DTCM_SIZE as u32, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MlCoreInterface for MlCore {
|
// TODO(jesionowski): Remove these when error handling is refactored.
|
||||||
fn set_wmmu(&mut self, sections: &ModelSections) {
|
// The status will be faulty iff the interrupt line is raised, and
|
||||||
// The length of the window is not the size of the window, but rather
|
// we won't have the fault registers on Springbok.
|
||||||
// the last address of the window. This saves us a bit in hardware:
|
fn get_dtcm_slice() -> &'static mut [u32] {
|
||||||
// 0x400000 is 23 bits vs. 0x3FFFFF 22 bits.
|
unsafe { slice::from_raw_parts_mut(dtcm, DTCM_SIZE / size_of::<u32>()) }
|
||||||
vc_top::set_immu_window_offset(0, sections.instructions.addr);
|
}
|
||||||
vc_top::set_immu_window_length(0, sections.instructions.size - 1);
|
|
||||||
vc_top::set_immu_window_permission(0, vc_top::Permission::Read);
|
pub fn get_return_code() -> u32 {
|
||||||
|
const RC_OFFSET: usize = 0x3FFFEE;
|
||||||
vc_top::set_dmmu_window_offset(0, sections.data.addr);
|
get_dtcm_slice()[RC_OFFSET]
|
||||||
vc_top::set_dmmu_window_length(0, sections.data.size - 1);
|
}
|
||||||
vc_top::set_dmmu_window_permission(0, vc_top::Permission::ReadAndWrite);
|
|
||||||
}
|
pub fn get_fault_register() -> u32 {
|
||||||
|
const FAULT_OFFSET: usize = 0x3FFFEF;
|
||||||
fn enable_interrupts(&mut self, enable: bool) {
|
get_dtcm_slice()[FAULT_OFFSET]
|
||||||
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()
|
|
||||||
.with_freeze(false)
|
|
||||||
.with_vc_reset(false)
|
|
||||||
.with_pc_start(0);
|
|
||||||
vc_top::set_ctrl(ctrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loads the model into the TCM.
|
|
||||||
fn load_image(&mut self, frames: &ObjDescBundle) -> Result<ModelSections, &'static str> {
|
|
||||||
let mut image = BundleImage::new(frames);
|
|
||||||
let mut itcm_found = false;
|
|
||||||
let mut dtcm_found = false;
|
|
||||||
// Size of windows is filled in below.
|
|
||||||
let mut iwindow = Window {
|
|
||||||
addr: ITCM_PADDR,
|
|
||||||
size: 0,
|
|
||||||
};
|
|
||||||
let mut dwindow = Window {
|
|
||||||
addr: DTCM_PADDR,
|
|
||||||
size: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
clear_tcm();
|
|
||||||
// NB: we require both ITCM & DTCM sections and that only one
|
|
||||||
// instance of each is present
|
|
||||||
while let Some(section) = image.next_section() {
|
|
||||||
let slice = if section.vaddr == ITCM_PADDR {
|
|
||||||
if itcm_found {
|
|
||||||
return Err("dup ITCM");
|
|
||||||
}
|
|
||||||
itcm_found = true;
|
|
||||||
|
|
||||||
if section.fsize > ITCM_SIZE {
|
|
||||||
return Err("ITCM too big");
|
|
||||||
}
|
|
||||||
iwindow.size = round_up(section.msize, WMMU_PAGE_SIZE);
|
|
||||||
unsafe { slice::from_raw_parts_mut(itcm as *mut u8, ITCM_SIZE) }
|
|
||||||
} else if section.vaddr == DTCM_PADDR {
|
|
||||||
if dtcm_found {
|
|
||||||
return Err("dup DTCM");
|
|
||||||
}
|
|
||||||
dtcm_found = true;
|
|
||||||
|
|
||||||
if section.fsize > DTCM_SIZE {
|
|
||||||
return Err("DTCM section too big");
|
|
||||||
}
|
|
||||||
dwindow.size = round_up(section.msize, WMMU_PAGE_SIZE);
|
|
||||||
unsafe { slice::from_raw_parts_mut(dtcm as *mut u8, DTCM_SIZE) }
|
|
||||||
} else {
|
|
||||||
return Err("Unexpected section");
|
|
||||||
};
|
|
||||||
image
|
|
||||||
.read_exact(&mut slice[section.data_range()])
|
|
||||||
.map_err(|_| "section read error")?;
|
|
||||||
// TODO(jesionowski): Remove when clear_tcm is fully implemented.
|
|
||||||
slice[section.zero_range()].fill(0x00);
|
|
||||||
}
|
|
||||||
if !itcm_found || !dtcm_found {
|
|
||||||
return Err("Incomplete");
|
|
||||||
}
|
|
||||||
Ok(ModelSections {
|
|
||||||
instructions: iwindow,
|
|
||||||
data: dwindow,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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() {
|
|
||||||
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() {
|
|
||||||
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() {
|
|
||||||
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() {
|
|
||||||
let mut intr_state = vc_top::get_intr_state();
|
|
||||||
intr_state.set_data_fault(true);
|
|
||||||
vc_top::set_intr_state(intr_state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -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()) }
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user