Source code for quantify_scheduler.backends.qblox.register_manager
# Repository: https://gitlab.com/quantify-os/quantify-scheduler
# Licensed according to the LICENCE file on the main branch
"""Utility class for dynamically allocating registers for Qblox sequencers."""
from __future__ import annotations
from quantify_scheduler.backends.qblox import constants
[docs]
class RegisterManager:
"""Utility class that keeps track of all the registers that are still available."""
def __init__(self) -> None:
[docs]
self._available_registers: list[str] = [
f"R{idx}" for idx in range(constants.NUMBER_OF_REGISTERS)
]
[docs]
def allocate_register(self) -> str:
"""
Allocates a register to be used within the q1asm program.
Returns
-------
:
A register that can be used.
Raises
------
IndexError
When the RegisterManager runs out of registers to allocate.
"""
if len(self.available_registers) < 1:
raise IndexError(
"Out of registers. Attempting to use more registers than "
"available in the Q1 sequence processor. This can be "
"caused, e.g., by attempting to use too many acquisition "
"channels."
)
return self._available_registers.pop(0)
[docs]
def free_register(self, register: str) -> None:
"""
Frees up a register to be reused.
Parameters
----------
register
The register to free up.
Raises
------
ValueError
The value provided is not a valid register.
RuntimeError
Attempting to free a register that is already free.
"""
_verify_valid_register(register)
if register in self.available_registers:
raise RuntimeError(
f"Attempting to free register '{register}', but this register is not inuse."
)
self._available_registers.insert(0, register) # LIFO
@property
[docs]
def available_registers(self) -> list[str]:
"""
Getter for the available registers.
Returns
-------
:
A copy of the list containing all the available registers.
"""
return self._available_registers[:]
[docs]
def _verify_valid_register(register_name: str) -> None:
"""
Verifies whether the passed name is a valid register name.
Raises on any of the conditions:
1. ``register_name`` does not start with "R" or
2. ``register_name`` does not have an integer next
3. the integer is higher than the number of registers in the sequence processor
4. the integer is negative valued
Parameters
----------
register_name
The register to verify.
Raises
------
ValueError
Invalid register name passed.
"""
if not register_name:
raise ValueError("Register can not be None or empty string")
if register_name[0] != "R":
raise ValueError(
f"Invalid register '{register_name}'. The register should start with a capital 'R'"
)
if not register_name[1:].isdigit():
raise ValueError(
f"Invalid register '{register_name}'. The correct format is 'R' followed by digits"
)
register_idx: int = int(register_name[1:])
if register_idx < 0 or register_idx > constants.NUMBER_OF_REGISTERS:
raise ValueError(
f"The register index '{register_name}' should be between "
f"0 and {constants.NUMBER_OF_REGISTERS}"
)