Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: FENCE blocks qubits, not frames #144

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 66 additions & 24 deletions src/program/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use petgraph::graphmap::GraphMap;
use petgraph::Directed;

use crate::instruction::{
FrameIdentifier, Instruction, Jump, JumpUnless, JumpWhen, Label, MeasureCalibrationDefinition,
MemoryReference,
self, FrameIdentifier, Instruction, Jump, JumpUnless, JumpWhen, Label,
MeasureCalibrationDefinition, MemoryReference, Qubit,
};
use crate::{instruction::InstructionRole, program::Program};

Expand Down Expand Up @@ -88,7 +88,7 @@ pub enum ExecutionDependency {
/// The instructions share a reference frame
ReferenceFrame,

/// The ordering between these two instructions must remain unchanged
/// The ordering between these two instructions must remain unchanged from the input program
StableOrdering,
}

Expand Down Expand Up @@ -299,6 +299,7 @@ impl InstructionBlock {

// Store the instruction index of the last instruction to block that frame
let mut last_instruction_by_frame: HashMap<FrameIdentifier, PreviousNodes> = HashMap::new();
let mut last_instruction_by_qubit: HashMap<Qubit, PreviousNodes> = HashMap::new();

// Store memory access reads and writes. Key is memory region name.
// NOTE: this may be refined to serialize by memory region offset rather than by entire region.
Expand All @@ -321,34 +322,69 @@ impl InstructionBlock {
.get_frames_for_instruction(instruction, false)
.unwrap_or_default();

let blocked_frames = program
.get_frames_for_instruction(instruction, true)
.unwrap_or_default();
if let Instruction::Fence(instruction::Fence { qubits }) = instruction {
let qubits = if qubits.is_empty() {
program.get_used_qubits()
} else {
qubits.iter().cloned().collect()
};

for qubit in qubits {
for previous_node_id in last_instruction_by_qubit
.entry(qubit)
.or_default()
.get_dependencies_for_next_user(node)
{
add_dependency!(graph, previous_node_id => node, ExecutionDependency::StableOrdering)
}
}

let blocked_but_not_used_frames = blocked_frames.difference(&used_frames);
Ok(())
} else {
let blocked_frames = program
.get_frames_for_instruction(instruction, true)
.unwrap_or_default();

for frame in &used_frames {
let previous_node_ids = last_instruction_by_frame
.entry((*frame).clone())
.or_default()
.get_dependencies_for_next_user(node);
let blocked_but_not_used_frames = blocked_frames.difference(&used_frames);

for previous_node_id in previous_node_ids {
add_dependency!(graph, previous_node_id => node, ExecutionDependency::ReferenceFrame);
for frame in &used_frames {
let previous_node_ids = last_instruction_by_frame
.entry((*frame).clone())
.or_default()
.get_dependencies_for_next_user(node);

for previous_node_id in previous_node_ids {
add_dependency!(graph, previous_node_id => node, ExecutionDependency::ReferenceFrame);
}
}
}

for frame in blocked_but_not_used_frames {
if let Some(previous_node_id) = last_instruction_by_frame
.entry((*frame).clone())
.or_default()
.get_dependency_for_next_blocker(node)
{
add_dependency!(graph, previous_node_id => node, ExecutionDependency::ReferenceFrame);
for frame in blocked_but_not_used_frames {
if let Some(previous_node_id) = last_instruction_by_frame
.entry((*frame).clone())
.or_default()
.get_dependency_for_next_blocker(node)
{
add_dependency!(graph, previous_node_id => node, ExecutionDependency::ReferenceFrame);
}
}
}

Ok(())
let used_qubits = used_frames.iter().fold(HashSet::new(), |mut agg, el| {
agg.extend(&el.qubits);
agg
});

for qubit in used_qubits {
if let Some(previous_node_id) = last_instruction_by_qubit
.entry((*qubit).clone())
.or_default()
.get_dependency_for_next_blocker(node)
{
add_dependency!(graph, previous_node_id => node, ExecutionDependency::StableOrdering)
}
}

Ok(())
}
}
InstructionRole::ControlFlow => Err(ScheduleError {
instruction_index: Some(index),
Expand Down Expand Up @@ -396,6 +432,12 @@ impl InstructionBlock {
}
}

for previous_nodes in last_instruction_by_qubit.into_values() {
for node in previous_nodes.drain() {
add_dependency!(graph, node => ScheduledGraphNode::BlockEnd, ExecutionDependency::StableOrdering);
}
}

// Examine all "pending" memory operations for all regions
let remaining_dependencies = pending_memory_access
.drain()
Expand Down
14 changes: 12 additions & 2 deletions src/program/graphviz_dot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,6 @@ NONBLOCKING PULSE 2 \"rf\" test(duration: 1e6)
PULSE 0 \"rf\" test(duration: 1e6)
NONBLOCKING PULSE 0 \"ro_tx\" test(duration: 1e6)
PULSE 0 \"rf\" test(duration: 1e6)
FENCE 0
FENCE 0
"
);

Expand Down Expand Up @@ -352,6 +350,18 @@ FENCE 1
"
);

build_dot_format_snapshot_test_case!(
non_overlapping_fence,
r#"
FENCE 0
NONBLOCKING PULSE 0 "rf" drag_gaussian(alpha: (-0.95146893464447))
FENCE 0
FENCE 1
NONBLOCKING PULSE 1 "rf" drag_gaussian(alpha: (-1.3853631708424974))
FENCE 1
"#
);

build_dot_format_snapshot_test_case!(
jump,
"DECLARE ro BIT
Expand Down
44 changes: 37 additions & 7 deletions src/program/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashSet;
use std::collections::{BTreeMap, HashSet};

use crate::expression::Expression;
use crate::instruction::{
Expand All @@ -22,6 +22,7 @@ use crate::instruction::{
Measurement, MemoryReference, Move, Pulse, RawCapture, SetPhase, SetScale, ShiftPhase, Store,
UnaryLogic, Vector, WaveformInvocation,
};
use crate::Program;

#[derive(Clone, Debug, Hash, PartialEq)]
pub struct MemoryRegion {
Expand Down Expand Up @@ -228,13 +229,8 @@ impl Instruction {
reads: set_from_memory_references![waveform.get_memory_references()],
..Default::default()
},
Instruction::RawCapture(RawCapture {
duration,
memory_reference,
..
}) => MemoryAccesses {
Instruction::RawCapture(RawCapture { duration, .. }) => MemoryAccesses {
reads: set_from_memory_references![duration.get_memory_references()],
captures: set_from_memory_references![vec![memory_reference]],
..Default::default()
},
Instruction::SetPhase(SetPhase { phase: expr, .. })
Expand Down Expand Up @@ -315,3 +311,37 @@ impl WaveformInvocation {
result
}
}

impl Program {
/// Return all the ways in which a particular [`MemoryReference`] is accessed within a [`Program`].
///
/// Note that this does not account for calibration expansion; for accurate results, ensure
/// that the program has been fully expanded first.
pub fn get_memory_access_types_by_region(&self) -> BTreeMap<String, HashSet<MemoryAccessType>> {
let mut result: BTreeMap<String, HashSet<MemoryAccessType>> = BTreeMap::new();

for instruction in &self.instructions {
let accesses = instruction.get_memory_accesses();
for region in accesses.reads {
result
.entry(region)
.or_default()
.insert(MemoryAccessType::Read);
}
for region in accesses.writes {
result
.entry(region)
.or_default()
.insert(MemoryAccessType::Write);
}
for region in accesses.captures {
result
.entry(region)
.or_default()
.insert(MemoryAccessType::Capture);
}
}

result
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ digraph {
"measure_start" -> "measure_1" [label="frame"];
"measure_start" -> "measure_end" [label="ordering"];
"measure_0" [shape=rectangle, label="[0] NONBLOCKING PULSE 0 \"ro_tx\" test(duration: 1000000)"];
"measure_0" -> "measure_end" [label="frame"];
"measure_0" -> "measure_end" [label="frame
ordering"];
"measure_1" [shape=rectangle, label="[1] NONBLOCKING CAPTURE 0 \"ro_rx\" test(duration: 1000000) ro[0]"];
"measure_1" -> "measure_end" [label="await capture
frame"];
frame
ordering"];
"measure_end" [shape=circle, label="end"];
}
"measure_end" -> "end_start" [label="if ro[0] == 0"];
Expand All @@ -29,7 +31,8 @@ frame"];
"feedback_start" -> "feedback_end" [label="frame
ordering"];
"feedback_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"];
"feedback_0" -> "feedback_end" [label="frame"];
"feedback_0" -> "feedback_end" [label="frame
ordering"];
"feedback_end" [shape=circle, label="end"];
}
"feedback_end" -> "measure_start" [label="always"];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ digraph {
ordering"];
"block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1e-6)"];
"block_0_0" -> "block_0_2" [label="frame"];
"block_0_0" -> "block_0_end" [label="frame"];
"block_0_0" -> "block_0_end" [label="frame
ordering"];
"block_0_1" [shape=rectangle, label="[1] PULSE 1 \"rf\" test(duration: 1e-6)"];
"block_0_1" -> "block_0_2" [label="frame"];
"block_0_1" -> "block_0_end" [label="frame"];
"block_0_1" -> "block_0_end" [label="frame
ordering"];
"block_0_2" [shape=rectangle, label="[2] PULSE 0 1 \"cz\" test(duration: 1e-6)"];
"block_0_2" -> "block_0_end" [label="frame"];
"block_0_2" -> "block_0_end" [label="frame
ordering"];
"block_0_end" [shape=circle, label="end"];
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ ordering"];
"block_0_0" [shape=rectangle, label="[0] NONBLOCKING PULSE 0 \"ro_tx\" test(duration: 1000000)"];
"block_0_0" -> "block_0_1" [label="frame"];
"block_0_0" -> "block_0_2" [label="frame"];
"block_0_0" -> "block_0_end" [label="frame"];
"block_0_0" -> "block_0_end" [label="frame
ordering"];
"block_0_1" [shape=rectangle, label="[1] PULSE 0 \"rf\" test(duration: 1000000)"];
"block_0_1" -> "block_0_2" [label="frame"];
"block_0_1" -> "block_0_end" [label="frame"];
"block_0_1" -> "block_0_end" [label="frame
ordering"];
"block_0_2" [shape=rectangle, label="[2] PULSE 0 \"ro_rx\" test(duration: 1000000)"];
"block_0_2" -> "block_0_end" [label="frame"];
"block_0_2" -> "block_0_end" [label="frame
ordering"];
"block_0_end" [shape=circle, label="end"];
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,20 @@ digraph {
"block_0_start" [shape=circle, label="start"];
"block_0_start" -> "block_0_0" [label="frame"];
"block_0_start" -> "block_0_1" [label="frame"];
"block_0_start" -> "block_0_3" [label="frame"];
"block_0_start" -> "block_0_end" [label="ordering"];
"block_0_start" -> "block_0_end" [label="frame
ordering"];
"block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"];
"block_0_0" -> "block_0_1" [label="frame"];
"block_0_0" -> "block_0_2" [label="frame"];
"block_0_0" -> "block_0_3" [label="frame"];
"block_0_0" -> "block_0_end" [label="frame
ordering"];
"block_0_1" [shape=rectangle, label="[1] NONBLOCKING PULSE 0 \"ro_tx\" test(duration: 1000000)"];
"block_0_1" -> "block_0_2" [label="frame"];
"block_0_1" -> "block_0_3" [label="frame"];
"block_0_1" -> "block_0_end" [label="frame
ordering"];
"block_0_2" [shape=rectangle, label="[2] PULSE 0 \"rf\" test(duration: 1000000)"];
"block_0_2" -> "block_0_3" [label="frame"];
"block_0_3" [shape=rectangle, label="[3] FENCE 0"];
"block_0_3" -> "block_0_4" [label="frame"];
"block_0_4" [shape=rectangle, label="[4] FENCE 0"];
"block_0_4" -> "block_0_end" [label="frame"];
"block_0_2" -> "block_0_end" [label="frame
ordering"];
"block_0_end" [shape=circle, label="end"];
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,23 @@ digraph {
ordering"];
"block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"];
"block_0_0" -> "block_0_1" [label="frame"];
"block_0_0" -> "block_0_end" [label="frame"];
"block_0_0" -> "block_0_end" [label="frame
ordering"];
"block_0_1" [shape=rectangle, label="[1] PULSE 0 \"rf\" test(duration: 1000000)"];
"block_0_1" -> "block_0_2" [label="frame"];
"block_0_1" -> "block_0_end" [label="frame"];
"block_0_1" -> "block_0_end" [label="frame
ordering"];
"block_0_2" [shape=rectangle, label="[2] PULSE 0 \"rf\" test(duration: 1000000)"];
"block_0_2" -> "block_0_3" [label="frame"];
"block_0_2" -> "block_0_end" [label="frame"];
"block_0_2" -> "block_0_end" [label="frame
ordering"];
"block_0_3" [shape=rectangle, label="[3] PULSE 0 \"rf\" test(duration: 1000000)"];
"block_0_3" -> "block_0_4" [label="frame"];
"block_0_3" -> "block_0_end" [label="frame"];
"block_0_3" -> "block_0_end" [label="frame
ordering"];
"block_0_4" [shape=rectangle, label="[4] PULSE 0 \"rf\" test(duration: 1000000)"];
"block_0_4" -> "block_0_end" [label="frame"];
"block_0_4" -> "block_0_end" [label="frame
ordering"];
"block_0_end" [shape=circle, label="end"];
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ digraph {
"block_0_start" -> "block_0_end" [label="frame
ordering"];
"block_0_0" [shape=rectangle, label="[0] PULSE 0 \"rf\" test(duration: 1000000)"];
"block_0_0" -> "block_0_end" [label="frame"];
"block_0_0" -> "block_0_end" [label="frame
ordering"];
"block_0_1" [shape=rectangle, label="[1] PULSE 1 \"rf\" test(duration: 1000000)"];
"block_0_1" -> "block_0_end" [label="frame"];
"block_0_1" -> "block_0_end" [label="frame
ordering"];
"block_0_2" [shape=rectangle, label="[2] PULSE 2 \"rf\" test(duration: 1000000)"];
"block_0_2" -> "block_0_end" [label="frame"];
"block_0_2" -> "block_0_end" [label="frame
ordering"];
"block_0_end" [shape=circle, label="end"];
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ digraph {
"block_0_start" -> "block_0_2" [label="frame"];
"block_0_start" -> "block_0_end" [label="ordering"];
"block_0_0" [shape=rectangle, label="[0] NONBLOCKING PULSE 0 \"rf\" test(duration: 1000000)"];
"block_0_0" -> "block_0_end" [label="frame"];
"block_0_0" -> "block_0_end" [label="frame
ordering"];
"block_0_1" [shape=rectangle, label="[1] NONBLOCKING PULSE 1 \"rf\" test(duration: 1000000)"];
"block_0_1" -> "block_0_end" [label="frame"];
"block_0_1" -> "block_0_end" [label="frame
ordering"];
"block_0_2" [shape=rectangle, label="[2] NONBLOCKING PULSE 2 \"rf\" test(duration: 1000000)"];
"block_0_2" -> "block_0_end" [label="frame"];
"block_0_2" -> "block_0_end" [label="frame
ordering"];
"block_0_end" [shape=circle, label="end"];
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ digraph {
label="block_0";
node [style="filled"];
"block_0_start" [shape=circle, label="start"];
"block_0_start" -> "block_0_0" [label="frame"];
"block_0_start" -> "block_0_end" [label="ordering"];
"block_0_0" [shape=rectangle, label="[0] FENCE"];
"block_0_0" -> "block_0_end" [label="frame"];
"block_0_end" [shape=circle, label="end"];
}
}
Expand Down
Loading