use crate::exec::signals::ControlFlow;
use crate::uarch::pipeline::exception::ExceptionStage;
use crate::uarch::pipeline::rename::vec_prf::{VecPhysReg, VecPhysRegFile};
use super::issue_queue::IssueQueue;
use super::{O3Engine, PendingResult};
pub(super) fn wake_vector_dests(
vec_prf: &mut VecPhysRegFile,
issue_queue: &mut IssueQueue,
dests: &[VecPhysReg],
) {
for ® in dests {
vec_prf.mark_ready(reg);
}
for ® in dests {
issue_queue.wakeup_vec_phys(reg, vec_prf);
}
}
impl O3Engine {
fn take_finished_results(&mut self, now: u64, slots: usize) -> Vec<PendingResult> {
let (mut finished, waiting): (Vec<_>, Vec<_>) = std::mem::take(&mut self.pending_results)
.into_iter()
.partition(|p| p.complete_cycle <= now);
finished.sort_by(|a, b| {
a.complete_cycle
.cmp(&b.complete_cycle)
.then_with(|| a.entry.rob_tag.age_cmp(b.entry.rob_tag))
});
self.pending_results = waiting;
self.pending_results.extend(finished.split_off(slots.min(finished.len())));
finished
}
pub(super) fn writeback_finished_results(&mut self, now: u64, slots: usize) -> usize {
let finished = self.take_finished_results(now, slots);
let used = finished.len();
for PendingResult { entry, .. } in finished {
if let Some(trap) = entry.trap {
let stage = entry.exception_stage.unwrap_or(ExceptionStage::Execute);
self.rob.fault(entry.rob_tag, trap, stage);
continue;
}
let val = if entry.ctrl.control_flow == ControlFlow::Jump {
entry.pc.wrapping_add(entry.inst_size.as_u64())
} else {
entry.alu
};
if entry.fp_flags != 0 {
self.rob.set_fp_flags(entry.rob_tag, entry.fp_flags);
}
if let Some(info) = entry.sfence_vma {
self.rob.set_sfence_vma(entry.rob_tag, info);
}
self.rob.complete(entry.rob_tag, val);
self.prf.write(entry.rd_phys, val);
self.issue_queue.wakeup_phys(entry.rd_phys, val);
}
used
}
pub(super) fn complete_vector_results(&mut self, now: u64, mut slots: usize) {
let mut i = 0;
while i < self.vec_pending.len() {
let vp = &mut self.vec_pending[i];
if vp.should_wakeup(now) {
wake_vector_dests(
&mut self.vec_prf,
&mut self.issue_queue,
&vp.vd_phys[..vp.vd_count as usize],
);
vp.wakeup_fired = true;
}
if vp.is_complete(now) && slots > 0 {
slots -= 1;
if !vp.wakeup_fired {
wake_vector_dests(
&mut self.vec_prf,
&mut self.issue_queue,
&vp.vd_phys[..vp.vd_count as usize],
);
vp.wakeup_fired = true;
}
self.rob.complete(vp.rob_tag, 0);
let _ = self.vec_pending.swap_remove(i);
} else {
i += 1;
}
}
}
}