Skip to content

Commit

Permalink
Fixes Qiskit#7078: Introduce ClassicalIOChannel as a subclass of puls…
Browse files Browse the repository at this point in the history
…e.Channel

RegisterSlot, MemorySlot and SnapshotChannel now derive from this class. There are some tests to fix.
  • Loading branch information
pollyshaw committed Jul 19, 2022
1 parent f05d4b4 commit 0b1a111
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 23 deletions.
27 changes: 9 additions & 18 deletions qiskit/pulse/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,6 @@ def name(self) -> str:
"""Return the shorthand alias for this channel, which is based on its type and index."""
return f"{self.__class__.prefix}{self._index}"

@property
def is_schedulable(self) -> bool:
"""Return whether this channel can be independently scheduled"""
return True

def __repr__(self):
return f"{self.__class__.__name__}({self._index})"

Expand All @@ -170,6 +165,12 @@ class PulseChannel(Channel, metaclass=ABCMeta):
pass


class ClassicalIOChannel(Channel, metaclass=ABCMeta):
"""Base class of classical IO channels. These cannot have instructions scheduled on them."""

pass


class DriveChannel(PulseChannel):
"""Drive channels transmit signals to qubits which enact gate operations."""

Expand Down Expand Up @@ -197,7 +198,7 @@ class AcquireChannel(Channel):
prefix = "a"


class SnapshotChannel(Channel):
class SnapshotChannel(ClassicalIOChannel):
"""Snapshot channels are used to specify instructions for simulators."""

prefix = "s"
Expand All @@ -207,25 +208,15 @@ def __init__(self):
super().__init__(0)


class MemorySlot(Channel):
class MemorySlot(ClassicalIOChannel):
"""Memory slot channels represent classical memory storage."""

prefix = "m"

@property
def is_schedulable(self) -> bool:
"""Return whether this channel can be independently scheduled"""
return False


class RegisterSlot(Channel):
class RegisterSlot(ClassicalIOChannel):
"""Classical resister slot channels represent classical registers (low-latency classical
memory).
"""

prefix = "c"

@property
def is_schedulable(self) -> bool:
"""Return whether this channel can be independently scheduled"""
return False
12 changes: 8 additions & 4 deletions qiskit/pulse/instructions/delay.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from typing import Optional, Union, Tuple

from qiskit.circuit import ParameterExpression
from qiskit.pulse.channels import Channel
from qiskit.pulse.channels import Channel, ClassicalIOChannel
from qiskit.pulse.exceptions import PulseError
from qiskit.pulse.instructions.instruction import Instruction

Expand Down Expand Up @@ -51,11 +51,15 @@ def __init__(
name: Name of the delay for display purposes.
Raises:
PulseError: If `channel` cannot be delayed because it cannot be scheduled.
PulseError: If `channel` cannot be delayed because it is a classical IO channel.
"""
super().__init__(operands=(duration, channel), name=name)
if not channel.is_schedulable:
raise PulseError("Cannot delay chanel because it is not schedulable.")
if isinstance(channel, ClassicalIOChannel):
raise PulseError(
"Cannot delay channel {0} because it is a classical IO channel.".format(
channel.name
)
)

@property
def channel(self) -> Channel:
Expand Down
12 changes: 12 additions & 0 deletions qiskit/pulse/instructions/directives.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from typing import Optional, Tuple

from qiskit.pulse import channels as chans
from qiskit.pulse.channels import ClassicalIOChannel
from qiskit.pulse.exceptions import PulseError
from qiskit.pulse.instructions import instruction


Expand Down Expand Up @@ -44,7 +46,17 @@ def __init__(self, *channels: chans.Channel, name: Optional[str] = None):
Args:
channels: The channel that the barrier applies to.
name: Name of the directive for display purposes.
Raises:
PulseError: If one of the `channels` cannot be blocked because it is a classical IO channel.
"""
for channel in channels:
if isinstance(channel, ClassicalIOChannel):
raise PulseError(
"Cannot block channel {0} because it is a classical IO channel.".format(
channel.name
)
)

super().__init__(operands=tuple(channels), name=name)

@property
Expand Down
3 changes: 2 additions & 1 deletion qiskit/pulse/transforms/canonicalization.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import numpy as np

from qiskit.pulse import channels as chans, exceptions, instructions
from qiskit.pulse.channels import ClassicalIOChannel
from qiskit.pulse.exceptions import PulseError
from qiskit.pulse.exceptions import UnassignedDurationError
from qiskit.pulse.instruction_schedule_map import InstructionScheduleMap
Expand Down Expand Up @@ -475,7 +476,7 @@ def pad(
channels = channels or schedule.channels

for channel in channels:
if not channel.is_schedulable:
if isinstance(channel, ClassicalIOChannel):
continue
if channel not in schedule.channels:
schedule |= instructions.Delay(until, channel)
Expand Down

0 comments on commit 0b1a111

Please sign in to comment.