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

30 implement qoala runtime #74

Open
wants to merge 23 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
13 changes: 12 additions & 1 deletion netqasm/backend/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ def _instr_lea(self, subroutine_id: int, instr: ins.core.LeaInstruction) -> None
address = instr.address
self._logger.debug(f"Storing address of {address} to register {register}")
app_id = self._get_app_id(subroutine_id=subroutine_id)
assert isinstance(address.address, int)
self._set_register(app_id=app_id, register=register, value=address.address)

@inc_program_counter
Expand Down Expand Up @@ -623,6 +624,7 @@ def _instr_array(

def _initialize_array(self, app_id: int, address: Address, length: int) -> None:
arrays = self._app_arrays[app_id]
assert isinstance(address.address, int)
arrays.init_new_array(address.address, length)

def _handle_branch_instr(
Expand Down Expand Up @@ -713,6 +715,12 @@ def _compute_binary_classical_instr(
elif isinstance(instr, ins.core.SubmInstruction):
assert mod is not None
return (a - b) % mod
elif isinstance(instr, ins.core.MulInstruction):
return a * b
elif isinstance(instr, ins.core.DivInstruction):
return a // b
elif isinstance(instr, ins.core.RemInstruction):
return a % b
else:
raise ValueError(f"{instr} cannot be used as binary classical function")

Expand Down Expand Up @@ -1279,6 +1287,7 @@ def _update_shared_memory(
shared_memory.set_array_part(address=address, index=index, value=value) # type: ignore
elif isinstance(entry, Address):
self._logger.debug(f"Updating host about array {entry} with value {value}")
assert isinstance(entry.address, int)
address = entry.address
shared_memory.init_new_array(address=address, new_array=value) # type: ignore
else:
Expand Down Expand Up @@ -1315,6 +1324,7 @@ def _get_position_in_unit_module(self, app_id: int, address: int) -> int:
return position

def _get_array(self, app_id: int, address: Address) -> List[Optional[int]]:
assert isinstance(address.address, int)
return self._app_arrays[app_id]._get_array(address.address)

def _get_array_entry(self, app_id: int, array_entry: ArrayEntry) -> Optional[int]:
Expand All @@ -1340,7 +1350,8 @@ def _get_array_slice(
def _expand_array_part(
self, app_id: int, array_part: Union[ArrayEntry, ArraySlice]
) -> Tuple[int, Union[int, slice]]:
address: int = array_part.address.address
address = array_part.address.address
assert isinstance(address, int)
index: Union[int, slice]
if isinstance(array_part, ArrayEntry):
if isinstance(array_part.index, int):
Expand Down
2 changes: 1 addition & 1 deletion netqasm/lang/instr/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from .base import DebugInstruction, NetQASMInstruction
from .flavour import Flavour, NVFlavour, VanillaFlavour
from .flavour import Flavour, NVFlavour, TrappedIonFlavour, VanillaFlavour
39 changes: 36 additions & 3 deletions netqasm/lang/instr/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,14 @@ def from_operands(cls, operands: List[Union[Operand, int]]):
elif isinstance(imm0, Immediate):
pass
else:
assert isinstance(imm0, Template)
assert isinstance(imm0, Template) or isinstance(imm0, Register)
if isinstance(imm1, int):
imm1 = Immediate(value=imm1)
elif isinstance(imm1, Immediate):
pass
else:
assert isinstance(imm1, Template)
# We allow imm0, imm1 to be Templates
assert isinstance(imm1, Template) or isinstance(imm1, Register)
# We allow imm0, imm1 to be Templates OR registers
return cls(reg=reg, imm0=imm0, imm1=imm1) # type: ignore


Expand Down Expand Up @@ -262,6 +262,21 @@ class SetInstruction(base.RegImmInstruction):
def writes_to(self) -> List[Register]:
return [self.reg]

@classmethod
def from_operands(cls, operands: List[Union[Operand, int]]):
assert len(operands) == 2
reg, imm = operands
assert isinstance(reg, Register)

if isinstance(imm, int):
imm = Immediate(value=imm)
elif isinstance(imm, Immediate):
pass
else:
assert isinstance(imm, Template)

return cls(reg=reg, imm=imm) # type: ignore


@dataclass
class StoreInstruction(base.RegEntryInstruction):
Expand Down Expand Up @@ -429,6 +444,24 @@ class SubmInstruction(ClassicalOpModInstruction):
mnemonic: str = "subm"


@dataclass
class MulInstruction(ClassicalOpInstruction):
id: int = 200
mnemonic: str = "mul"


@dataclass
class DivInstruction(ClassicalOpInstruction):
id: int = 201
mnemonic: str = "div"


@dataclass
class RemInstruction(ClassicalOpInstruction):
id: int = 202
mnemonic: str = "rem"


@dataclass
class MeasInstruction(base.RegRegInstruction):
id: int = 32
Expand Down
22 changes: 21 additions & 1 deletion netqasm/lang/instr/flavour.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from dataclasses import dataclass
from typing import Dict, List, Optional, Type

from . import NetQASMInstruction, core, nv, vanilla
from . import NetQASMInstruction, core, nv, trapped_ion, vanilla


@dataclass
Expand Down Expand Up @@ -31,6 +31,9 @@ class InstrMap:
core.SubInstruction,
core.AddmInstruction,
core.SubmInstruction,
core.MulInstruction,
core.DivInstruction,
core.RemInstruction,
core.MeasInstruction,
core.MeasBasisInstruction,
core.CreateEPRInstruction,
Expand Down Expand Up @@ -121,3 +124,20 @@ def instrs(self):

def __init__(self):
super().__init__(self.instrs)


class TrappedIonFlavour(Flavour):
@property
def instrs(self):
return [
trapped_ion.RotZInstruction,
trapped_ion.AllQubitsRotXInstruction,
trapped_ion.AllQubitsRotYInstruction,
trapped_ion.AllQubitsRotZInstruction,
trapped_ion.AllQubitsInitInstruction,
trapped_ion.AllQubitsMeasInstruction,
trapped_ion.BichromaticInstruction,
]

def __init__(self):
super().__init__(self.instrs)
38 changes: 0 additions & 38 deletions netqasm/lang/instr/nv.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,6 @@
# Explicit instruction types in the NV flavour.


@dataclass
class GateXInstruction(core.SingleQubitInstruction):
id: int = 20
mnemonic: str = "x"

def to_matrix(self) -> np.ndarray:
return np.array([[0, 1], [1, 0]])


@dataclass
class GateYInstruction(core.SingleQubitInstruction):
id: int = 21
mnemonic: str = "y"

def to_matrix(self) -> np.ndarray:
return np.array([[0, -1j], [1j, 0]])


@dataclass
class GateZInstruction(core.SingleQubitInstruction):
id: int = 22
mnemonic: str = "z"

def to_matrix(self) -> np.ndarray:
return np.array([[1, 0], [0, -1]])


@dataclass
class GateHInstruction(core.SingleQubitInstruction):
id: int = 23
mnemonic: str = "h"

def to_matrix(self) -> np.ndarray:
X = GateXInstruction().to_matrix()
Z = GateZInstruction().to_matrix()
return (X + Z) / np.sqrt(2) # type: ignore


@dataclass
class RotXInstruction(core.RotationInstruction):
id: int = 27
Expand Down
131 changes: 131 additions & 0 deletions netqasm/lang/instr/trapped_ion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
from dataclasses import dataclass
from typing import List, Union

import numpy as np

from netqasm.lang.operand import Immediate, Operand, Register, Template
from netqasm.util.quantum_gates import get_rotation_matrix

from . import base, core


@dataclass # type: ignore
class AllQubitsRotationInstruction(base.ImmImmInstruction):
@property
def angle_num(self):
return self.imm0

@angle_num.setter
def angle_num(self, new_val: Immediate):
self.imm0 = new_val

@property
def angle_denom(self):
return self.imm1

@angle_denom.setter
def angle_denom(self, new_val: Immediate):
self.imm1 = new_val

@classmethod
def from_operands(cls, operands: List[Union[Operand, int]]):
assert len(operands) == 2
imm0, imm1 = operands

if isinstance(imm0, int):
imm0 = Immediate(value=imm0)
elif isinstance(imm0, Immediate):
pass
else:
assert isinstance(imm0, Template) or isinstance(imm0, Register)
if isinstance(imm1, int):
imm1 = Immediate(value=imm1)
elif isinstance(imm1, Immediate):
pass
else:
assert isinstance(imm1, Template) or isinstance(imm1, Register)
# We allow imm0, imm1 to be Templates OR registers
return cls(imm0=imm0, imm1=imm1) # type: ignore


@dataclass
class AllQubitsInitInstruction(base.NoOperandInstruction):
id: int = 42
mnemonic: str = "init_all"


@dataclass
class AllQubitsMeasInstruction(base.RegAddrInstruction):
id: int = 43
mnemonic: str = "meas_all"


@dataclass
class RotZInstruction(core.RotationInstruction):
id: int = 29
mnemonic: str = "rot_z"

def to_matrix(self) -> np.ndarray:
axis = [0, 0, 1]
angle = self.angle_num.value * np.pi / 2**self.angle_denom.value
return get_rotation_matrix(axis, angle)


@dataclass
class AllQubitsRotXInstruction(AllQubitsRotationInstruction):
id: int = 44
mnemonic: str = "rot_x_all"


@dataclass
class AllQubitsRotYInstruction(AllQubitsRotationInstruction):
id: int = 45
mnemonic: str = "rot_y_all"


@dataclass
class AllQubitsRotZInstruction(AllQubitsRotationInstruction):
id: int = 46
mnemonic: str = "rot_z_all"


@dataclass
class BichromaticInstruction(base.ImmImmInstruction):
id: int = 47
mnemonic: str = "bichromatic"

@property
def angle_num(self):
return self.imm0

@angle_num.setter
def angle_num(self, new_val: Immediate):
self.imm0 = new_val

@property
def angle_denom(self):
return self.imm1

@angle_denom.setter
def angle_denom(self, new_val: Immediate):
self.imm1 = new_val

@classmethod
def from_operands(cls, operands: List[Union[Operand, int]]):
assert len(operands) == 2
imm0, imm1 = operands

if isinstance(imm0, int):
imm0 = Immediate(value=imm0)
elif isinstance(imm0, Immediate):
pass
else:
assert isinstance(imm0, Template) or isinstance(imm0, Register)
if isinstance(imm1, int):
imm1 = Immediate(value=imm1)
elif isinstance(imm1, Immediate):
pass
else:
assert isinstance(imm1, Template) or isinstance(imm1, Register)
# We allow imm0, imm1 to be Templates OR registers
return cls(imm0=imm0, imm1=imm1) # type: ignore
10 changes: 10 additions & 0 deletions netqasm/lang/ir.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class GenericInstr(Enum):
QALLOC = auto()
# Initialization
INIT = auto()
INIT_ALL = auto()
ARRAY = auto()
SET = auto()
# Memory
Expand All @@ -41,6 +42,9 @@ class GenericInstr(Enum):
SUB = auto()
ADDM = auto()
SUBM = auto()
MUL = auto()
DIV = auto()
REM = auto()
# Single-qubit gates
X = auto()
Y = auto()
Expand All @@ -56,9 +60,15 @@ class GenericInstr(Enum):
# Two-qubit gates
CNOT = auto()
CPHASE = auto()
# All-qubit gates
ROT_X_ALL = auto()
ROT_Y_ALL = auto()
ROT_Z_ALL = auto()
BICHROMATIC = auto()
# Measurement
MEAS = auto()
MEAS_BASIS = auto()
MEAS_ALL = auto()
# Entanglement generation
CREATE_EPR = auto()
RECV_EPR = auto()
Expand Down
Loading
Loading