save stats per abb
This commit is contained in:
parent
926ad96b8e
commit
8417613cb2
@ -25,4 +25,4 @@ do
|
|||||||
done < <(find ./remote/timedump -maxdepth 2 -type 'f' -iregex '.*\.case')
|
done < <(find ./remote/timedump -maxdepth 2 -type 'f' -iregex '.*\.case')
|
||||||
|
|
||||||
# echo "${PLOTS[@]}"
|
# echo "${PLOTS[@]}"
|
||||||
snakemake -c 6 "${PLOTS[@]}"
|
snakemake -c 6 --keep-incomplete "${PLOTS[@]}"
|
||||||
|
@ -192,7 +192,30 @@ where
|
|||||||
let names : Vec<String> = observer.last_run.iter().map(|x| x.current_task.task_name.clone()).collect();
|
let names : Vec<String> = observer.last_run.iter().map(|x| x.current_task.task_name.clone()).collect();
|
||||||
match &self.dumpfile {
|
match &self.dumpfile {
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
std::fs::write(s,ron::to_string(&(&observer.last_trace,&observer.last_states,&observer.job_instances)).expect("Error serializing hashmap")).expect("Can not dump to file");
|
let per_task_metadata = if let Some(worst_instance) = observer.job_instances.iter().filter(|x| Some(x.2.clone()) == observer.select_task).max_by(|a,b| (a.1-a.0).cmp(&(b.1-b.0))) {
|
||||||
|
// extract computation time spent in each task and abb
|
||||||
|
let t : Vec<_> = observer.last_trace.iter().filter(|x| x.start_tick < worst_instance.1 && x.end_tick > worst_instance.0 ).cloned().collect();
|
||||||
|
// task_name -> addr -> (count, time)
|
||||||
|
let mut ret : HashMap<String, HashMap<u32, (usize, usize, u64)>> = HashMap::new();
|
||||||
|
let mut t2 = t.clone();
|
||||||
|
t2.sort_by_key(|x| x.get_task_name_unchecked());
|
||||||
|
t2.chunk_by_mut(|x,y| x.get_task_name_unchecked() == y.get_task_name_unchecked()).for_each(|x| {
|
||||||
|
x.sort_by_key(|y| y.abb.as_ref().unwrap().start);
|
||||||
|
x.chunk_by(|y,z| y.abb.as_ref().unwrap().start == z.abb.as_ref().unwrap().start).for_each(|y| {
|
||||||
|
match ret.get_mut(&y[0].get_task_name_unchecked()) {
|
||||||
|
Option::None => {
|
||||||
|
ret.insert(y[0].get_task_name_unchecked(), HashMap::from([(y[0].abb.as_ref().unwrap().start, (y.len(), y.iter().filter(|x| x.is_abb_end()).count(), y.iter().map(|z| z.get_exec_time()).sum::<_>()))]));
|
||||||
|
}
|
||||||
|
Some(x) => {
|
||||||
|
x.insert(y[0].abb.as_ref().unwrap().start, (y.len(), y.iter().filter(|x| x.is_abb_end()).count(), y.iter().map(|z| z.get_exec_time()).sum()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
dbg!(&ret);
|
||||||
|
ret
|
||||||
|
} else {HashMap::new()};
|
||||||
|
std::fs::write(s,ron::to_string(&(&observer.last_trace,&observer.last_states,&observer.job_instances,per_task_metadata)).expect("Error serializing hashmap")).expect("Can not dump to file");
|
||||||
self.dumpfile = None
|
self.dumpfile = None
|
||||||
},
|
},
|
||||||
Option::None => if self.dump_metadata {println!("{:?}\n{:?}",observer.last_run,names);}
|
Option::None => if self.dump_metadata {println!("{:?}\n{:?}",observer.last_run,names);}
|
||||||
|
@ -194,6 +194,7 @@ pub struct ExecInterval {
|
|||||||
pub end_state: u64,
|
pub end_state: u64,
|
||||||
pub start_capture: (CaptureEvent, String),
|
pub start_capture: (CaptureEvent, String),
|
||||||
pub end_capture: (CaptureEvent, String),
|
pub end_capture: (CaptureEvent, String),
|
||||||
|
pub interval_name: String,
|
||||||
pub level: u8,
|
pub level: u8,
|
||||||
tick_spend_preempted: u64,
|
tick_spend_preempted: u64,
|
||||||
pub abb: Option<AtomicBasicBlock>
|
pub abb: Option<AtomicBasicBlock>
|
||||||
@ -228,6 +229,20 @@ impl ExecInterval {
|
|||||||
pub fn get_hash_index(&self) -> (u64, u64) {
|
pub fn get_hash_index(&self) -> (u64, u64) {
|
||||||
return (self.start_state, self.abb.as_ref().expect("ABB not set").get_hash())
|
return (self.start_state, self.abb.as_ref().expect("ABB not set").get_hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_task_name(&self) -> Option<String> {
|
||||||
|
self.abb.as_ref().map(|x| x.instance_name.clone()).flatten()
|
||||||
|
}
|
||||||
|
pub fn get_task_name_unchecked(&self) -> String {
|
||||||
|
self.get_task_name().unwrap_or_else(|| "unknown".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_abb_end(&self) -> bool {
|
||||||
|
match self.end_capture.0 {
|
||||||
|
CaptureEvent::APIStart | CaptureEvent::APIEnd | CaptureEvent::ISREnd | CaptureEvent::End => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper around Vec<RefinedFreeRTOSSystemState> to attach as Metadata
|
// Wrapper around Vec<RefinedFreeRTOSSystemState> to attach as Metadata
|
||||||
@ -280,7 +295,8 @@ pub struct AtomicBasicBlock {
|
|||||||
start: GuestAddr,
|
start: GuestAddr,
|
||||||
ends: HashSet<GuestAddr>,
|
ends: HashSet<GuestAddr>,
|
||||||
level: u8,
|
level: u8,
|
||||||
instance_id: usize
|
instance_id: usize,
|
||||||
|
instance_name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for AtomicBasicBlock {
|
impl PartialEq for AtomicBasicBlock {
|
||||||
@ -308,7 +324,7 @@ impl fmt::Display for AtomicBasicBlock {
|
|||||||
for end in &self.ends {
|
for end in &self.ends {
|
||||||
ends_str.push_str(&format!("0x{:#x}, ", end));
|
ends_str.push_str(&format!("0x{:#x}, ", end));
|
||||||
}
|
}
|
||||||
write!(f, "ABB {{ level: {}, start: 0x{:#x}, ends: [{}]}}", self.level, self.start, ends_str.trim().trim_matches(','))
|
write!(f, "ABB {} {{ level: {}, start: 0x{:#x}, ends: [{}]}}", &self.instance_name.as_ref().unwrap_or(&"".to_string()), self.level, self.start, ends_str.trim().trim_matches(','))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl fmt::Debug for AtomicBasicBlock {
|
impl fmt::Debug for AtomicBasicBlock {
|
||||||
@ -317,7 +333,7 @@ impl fmt::Debug for AtomicBasicBlock {
|
|||||||
for end in &self.ends {
|
for end in &self.ends {
|
||||||
ends_str.push_str(&format!("{:#x}, ", end));
|
ends_str.push_str(&format!("{:#x}, ", end));
|
||||||
}
|
}
|
||||||
write!(f, "ABB {{ level: {}, start: {:#x}, ends: [{}]}}", self.level, self.start, ends_str.trim().trim_matches(','))
|
write!(f, "ABB {} {{ level: {}, start: 0x{:#x}, ends: [{}]}}", &self.instance_name.as_ref().unwrap_or(&"".to_string()), self.level, self.start, ends_str.trim().trim_matches(','))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ where
|
|||||||
let observer = &self;
|
let observer = &self;
|
||||||
let mut worst_case_per_task = HashMap::new();
|
let mut worst_case_per_task = HashMap::new();
|
||||||
observer.job_instances.iter().for_each(|x| {
|
observer.job_instances.iter().for_each(|x| {
|
||||||
let time = (x.1-x.0);
|
let time = x.1-x.0;
|
||||||
if worst_case_per_task.get(&x.2).is_some() {
|
if worst_case_per_task.get(&x.2).is_some() {
|
||||||
let old = worst_case_per_task.get_mut(&x.2).unwrap();
|
let old = worst_case_per_task.get_mut(&x.2).unwrap();
|
||||||
if time > *old {
|
if time > *old {
|
||||||
@ -191,7 +191,11 @@ fn tcb_list_to_vec_cached(list: List_t, dump: &mut HashMap<u32,rtos_struct>) ->
|
|||||||
ret.push(last_tcb);
|
ret.push(last_tcb);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Drains a List of raw SystemStates to produce a refined trace
|
/// Drains a List of raw SystemStates to produce a refined trace
|
||||||
|
/// returns:
|
||||||
|
/// - a Vec of ReducedFreeRTOSSystemStates
|
||||||
|
/// - a Vec of metadata tuples (qemu_tick, capture_event, capture_name, edge, mem_reads)
|
||||||
fn refine_system_states(mut input: Vec<RawFreeRTOSSystemState>) -> (Vec<ReducedFreeRTOSSystemState>, Vec<(u64, CaptureEvent, String, (u32, u32), HashSet<u32>)>) {
|
fn refine_system_states(mut input: Vec<RawFreeRTOSSystemState>) -> (Vec<ReducedFreeRTOSSystemState>, Vec<(u64, CaptureEvent, String, (u32, u32), HashSet<u32>)>) {
|
||||||
let mut ret = (Vec::<_>::new(), Vec::<_>::new());
|
let mut ret = (Vec::<_>::new(), Vec::<_>::new());
|
||||||
for mut i in input.drain(..) {
|
for mut i in input.drain(..) {
|
||||||
@ -412,6 +416,11 @@ fn get_release_response_pairs(rel: &Vec<(u64, String)>, resp: &Vec<(u64, String)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Transform the states and metadata into a list of ExecIntervals, along with a HashMap of states, a list of HashSets marking memory reads and a bool indicating success
|
/// Transform the states and metadata into a list of ExecIntervals, along with a HashMap of states, a list of HashSets marking memory reads and a bool indicating success
|
||||||
|
/// returns:
|
||||||
|
/// - a Vec of ExecIntervals
|
||||||
|
/// - a Vec of HashSets marking memory reads during these intervals
|
||||||
|
/// - a HashMap of ReducedFreeRTOSSystemStates by hash
|
||||||
|
/// - a bool indicating success
|
||||||
fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, CaptureEvent, String, (u32, u32), HashSet<u32>)>) -> (Vec<ExecInterval>, Vec<HashSet<u32>>, HashMap<u64, ReducedFreeRTOSSystemState>, bool) {
|
fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, CaptureEvent, String, (u32, u32), HashSet<u32>)>) -> (Vec<ExecInterval>, Vec<HashSet<u32>>, HashMap<u64, ReducedFreeRTOSSystemState>, bool) {
|
||||||
if trace.len() == 0 {return (Vec::new(), Vec::new(), HashMap::new(), true);}
|
if trace.len() == 0 {return (Vec::new(), Vec::new(), HashMap::new(), true);}
|
||||||
let mut isr_stack : VecDeque<u8> = VecDeque::from([]); // 2+ = ISR, 1 = systemcall, 0 = APP. Trace starts with an ISREnd and executes the app
|
let mut isr_stack : VecDeque<u8> = VecDeque::from([]); // 2+ = ISR, 1 = systemcall, 0 = APP. Trace starts with an ISREnd and executes the app
|
||||||
@ -427,6 +436,7 @@ fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, Capt
|
|||||||
table.insert(last_hash, trace[0].clone());
|
table.insert(last_hash, trace[0].clone());
|
||||||
for i in 0..trace.len()-1 {
|
for i in 0..trace.len()-1 {
|
||||||
let curr_name = trace[i].current_task.task_name.as_str();
|
let curr_name = trace[i].current_task.task_name.as_str();
|
||||||
|
// let mut interval_name = curr_name; // Name of the interval, either the task name or the isr/api funtion name
|
||||||
let level = match meta[i].1 {
|
let level = match meta[i].1 {
|
||||||
CaptureEvent::APIEnd => { // API end always exits towards the app
|
CaptureEvent::APIEnd => { // API end always exits towards the app
|
||||||
if !level_of_task.contains_key(curr_name) {
|
if !level_of_task.contains_key(curr_name) {
|
||||||
@ -440,6 +450,7 @@ fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, Capt
|
|||||||
level_of_task.insert(curr_name, 0);
|
level_of_task.insert(curr_name, 0);
|
||||||
}
|
}
|
||||||
*level_of_task.get_mut(curr_name).unwrap()=1;
|
*level_of_task.get_mut(curr_name).unwrap()=1;
|
||||||
|
// interval_name = &meta[i].2;
|
||||||
1
|
1
|
||||||
},
|
},
|
||||||
CaptureEvent::ISREnd => {
|
CaptureEvent::ISREnd => {
|
||||||
@ -449,11 +460,15 @@ fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, Capt
|
|||||||
}
|
}
|
||||||
// nested isr, TODO: Test level > 2
|
// nested isr, TODO: Test level > 2
|
||||||
if isr_stack.len() > 1 {
|
if isr_stack.len() > 1 {
|
||||||
|
// interval_name = ""; // We can't know which isr is running
|
||||||
isr_stack.pop_back().unwrap();
|
isr_stack.pop_back().unwrap();
|
||||||
*isr_stack.back().unwrap()
|
*isr_stack.back().unwrap()
|
||||||
} else {
|
} else {
|
||||||
isr_stack.pop_back();
|
isr_stack.pop_back();
|
||||||
// possibly go back to an api call that is still running for this task
|
// possibly go back to an api call that is still running for this task
|
||||||
|
if level_of_task.get(curr_name).unwrap() == &1 {
|
||||||
|
// interval_name = ""; // We can't know which api is running
|
||||||
|
}
|
||||||
*level_of_task.get(curr_name).unwrap()
|
*level_of_task.get(curr_name).unwrap()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -463,6 +478,7 @@ fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, Capt
|
|||||||
// &2
|
// &2
|
||||||
// } else {
|
// } else {
|
||||||
// regular case
|
// regular case
|
||||||
|
// interval_name = &meta[i].2;
|
||||||
if isr_stack.len() > 0 {
|
if isr_stack.len() > 0 {
|
||||||
let l = *isr_stack.back().unwrap();
|
let l = *isr_stack.back().unwrap();
|
||||||
isr_stack.push_back(l+1);
|
isr_stack.push_back(l+1);
|
||||||
@ -488,6 +504,7 @@ fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, Capt
|
|||||||
start_capture: (meta[i].1, meta[i].2.clone()),
|
start_capture: (meta[i].1, meta[i].2.clone()),
|
||||||
end_capture: (meta[i+1].1, meta[i+1].2.clone()),
|
end_capture: (meta[i+1].1, meta[i+1].2.clone()),
|
||||||
level: level,
|
level: level,
|
||||||
|
interval_name: String::new(),
|
||||||
tick_spend_preempted: 0,
|
tick_spend_preempted: 0,
|
||||||
abb: None
|
abb: None
|
||||||
});
|
});
|
||||||
@ -499,6 +516,7 @@ fn states2intervals(trace: Vec<ReducedFreeRTOSSystemState>, meta: Vec<(u64, Capt
|
|||||||
(ret, reads, table, t)
|
(ret, reads, table, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Marks which abbs were executed at each interval
|
||||||
fn add_abb_info(trace: &mut Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeRTOSSystemState>, edges: &Vec<(u32, u32)>) -> bool {
|
fn add_abb_info(trace: &mut Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeRTOSSystemState>, edges: &Vec<(u32, u32)>) -> bool {
|
||||||
let mut id_count = 0;
|
let mut id_count = 0;
|
||||||
let mut ret = true;
|
let mut ret = true;
|
||||||
@ -522,7 +540,7 @@ fn add_abb_info(trace: &mut Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeR
|
|||||||
// assert_eq!(open_abb, None);
|
// assert_eq!(open_abb, None);
|
||||||
ret &= open_abb.is_none();
|
ret &= open_abb.is_none();
|
||||||
open_abb_at_this_ret_addr_and_task.insert((edges[i].1, if trace[i].level<2 {&curr_name} else {""}), i);
|
open_abb_at_this_ret_addr_and_task.insert((edges[i].1, if trace[i].level<2 {&curr_name} else {""}), i);
|
||||||
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].0, ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}, instance_id: id_count})));
|
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].0, ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}, instance_id: id_count, instance_name: Some(trace[i].start_capture.1.clone())})));
|
||||||
id_count+=1;
|
id_count+=1;
|
||||||
},
|
},
|
||||||
// generic isr abb start
|
// generic isr abb start
|
||||||
@ -530,7 +548,7 @@ fn add_abb_info(trace: &mut Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeR
|
|||||||
// assert_eq!(open_abb, None);
|
// assert_eq!(open_abb, None);
|
||||||
ret &= open_abb.is_none();
|
ret &= open_abb.is_none();
|
||||||
open_abb_at_this_ret_addr_and_task.insert((edges[i].1, if trace[i].level<2 {&curr_name} else {""}), i);
|
open_abb_at_this_ret_addr_and_task.insert((edges[i].1, if trace[i].level<2 {&curr_name} else {""}), i);
|
||||||
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].0, ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}, instance_id: id_count})));
|
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].0, ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}, instance_id: id_count, instance_name: Some(trace[i].start_capture.1.clone())})));
|
||||||
id_count+=1;
|
id_count+=1;
|
||||||
},
|
},
|
||||||
// generic app abb start
|
// generic app abb start
|
||||||
@ -538,7 +556,7 @@ fn add_abb_info(trace: &mut Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeR
|
|||||||
// assert_eq!(open_abb, None);
|
// assert_eq!(open_abb, None);
|
||||||
ret &= open_abb.is_none();
|
ret &= open_abb.is_none();
|
||||||
open_abb_at_this_ret_addr_and_task.insert((edges[i].1, if trace[i].level<2 {&curr_name} else {""}), i);
|
open_abb_at_this_ret_addr_and_task.insert((edges[i].1, if trace[i].level<2 {&curr_name} else {""}), i);
|
||||||
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].0, ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}, instance_id: id_count})));
|
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].0, ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}, instance_id: id_count, instance_name: if trace[i].level<2 {Some(curr_name.clone())} else {None}})));
|
||||||
id_count+=1;
|
id_count+=1;
|
||||||
},
|
},
|
||||||
// generic continued blocks
|
// generic continued blocks
|
||||||
@ -547,7 +565,7 @@ fn add_abb_info(trace: &mut Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeR
|
|||||||
if trace[i].start_capture.1=="xPortPendSVHandler" && !task_has_started.contains(curr_name) {
|
if trace[i].start_capture.1=="xPortPendSVHandler" && !task_has_started.contains(curr_name) {
|
||||||
// assert_eq!(open_abb, None);
|
// assert_eq!(open_abb, None);
|
||||||
ret &= open_abb.is_none();
|
ret &= open_abb.is_none();
|
||||||
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: 0, ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}, instance_id: id_count})));
|
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: 0, ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}, instance_id: id_count, instance_name: Some(curr_name.clone())})));
|
||||||
id_count+=1;
|
id_count+=1;
|
||||||
open_abb_at_this_ret_addr_and_task.insert((edges[i].1, if trace[i].level<2 {&curr_name} else {""}), i);
|
open_abb_at_this_ret_addr_and_task.insert((edges[i].1, if trace[i].level<2 {&curr_name} else {""}), i);
|
||||||
task_has_started.insert(curr_name.clone());
|
task_has_started.insert(curr_name.clone());
|
||||||
@ -563,7 +581,7 @@ fn add_abb_info(trace: &mut Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeR
|
|||||||
// println!("Continued block with no start {} {} {:?} {:?} {:x}-{:x} {} {}", curr_name, trace[i].start_tick, trace[i].start_capture, trace[i].end_capture, edges[i].0, edges[i].1, task_has_started.contains(curr_name),trace[i].level);
|
// println!("Continued block with no start {} {} {:?} {:?} {:x}-{:x} {} {}", curr_name, trace[i].start_tick, trace[i].start_capture, trace[i].end_capture, edges[i].0, edges[i].1, task_has_started.contains(curr_name),trace[i].level);
|
||||||
// println!("{:x?}", open_abb_at_this_ret_addr_and_task);
|
// println!("{:x?}", open_abb_at_this_ret_addr_and_task);
|
||||||
ret = false;
|
ret = false;
|
||||||
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].1, ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}, instance_id: id_count})));
|
wip_abb_trace.push(Rc::new(RefCell::new(AtomicBasicBlock{start: edges[i].1, ends: HashSet::new(), level: if trace[i].level<2 {trace[i].level} else {2}, instance_id: id_count, instance_name: if trace[i].level<1 {Some(curr_name.clone())} else {None}})));
|
||||||
id_count+=1;
|
id_count+=1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -602,6 +620,7 @@ fn add_abb_info(trace: &mut Vec<ExecInterval>, table: &HashMap<u64, ReducedFreeR
|
|||||||
|
|
||||||
for i in 0..trace.len() {
|
for i in 0..trace.len() {
|
||||||
trace[i].abb = Some((*wip_abb_trace[i]).borrow().clone());
|
trace[i].abb = Some((*wip_abb_trace[i]).borrow().clone());
|
||||||
|
trace[i].interval_name = (*wip_abb_trace[i]).borrow().instance_name.clone().unwrap_or(String::from(""));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,10 @@ pub fn tick_to_time(ticks: u64) -> Duration {
|
|||||||
Duration::from_nanos((ticks << QEMU_ICOUNT_SHIFT) as u64)
|
Duration::from_nanos((ticks << QEMU_ICOUNT_SHIFT) as u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tick_to_ms(ticks: u64) -> f32 {
|
||||||
|
(Duration::from_nanos(ticks << QEMU_ICOUNT_SHIFT).as_micros() as f32/10.0).round()/100.0
|
||||||
|
}
|
||||||
|
|
||||||
//========== Metadata
|
//========== Metadata
|
||||||
#[derive(Debug, SerdeAny, Serialize, Deserialize)]
|
#[derive(Debug, SerdeAny, Serialize, Deserialize)]
|
||||||
pub struct QemuIcountMetadata {
|
pub struct QemuIcountMetadata {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user