Skip to content

Commit 58b65c3

Browse files
authored
Squin Dialect Address Analysis (#4)
* Move from bloqade to bloqade-circuit WIP on analysis * Saving comments/work from last sync with Roger * completed unit tests * fix isort * fix unit test, remove leftover print statements * remove commented out code for wire dialect wrapping, not possible to handle multiple return results
1 parent 86d5da0 commit 58b65c3

File tree

15 files changed

+339
-14
lines changed

15 files changed

+339
-14
lines changed

src/bloqade/analysis/address/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
NotQubit as NotQubit,
55
AddressReg as AddressReg,
66
AnyAddress as AnyAddress,
7+
AddressWire as AddressWire,
78
AddressQubit as AddressQubit,
89
AddressTuple as AddressTuple,
910
)

src/bloqade/analysis/address/analysis.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212

1313
class AddressAnalysis(Forward[Address]):
14-
"""This analysis pass can be used to track the global addresses of qubits."""
14+
"""
15+
This analysis pass can be used to track the global addresses of qubits and wires.
16+
"""
1517

1618
keys = ["qubit.address"]
1719
lattice = Address

src/bloqade/analysis/address/impls.py

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,16 @@
66
from kirin.analysis import ForwardFrame, const
77
from kirin.dialects import cf, py, scf, func, ilist
88

9-
from .lattice import Address, NotQubit, AddressReg, AddressQubit, AddressTuple
9+
from bloqade import squin
10+
11+
from .lattice import (
12+
Address,
13+
NotQubit,
14+
AddressReg,
15+
AddressWire,
16+
AddressQubit,
17+
AddressTuple,
18+
)
1019
from .analysis import AddressAnalysis
1120

1221

@@ -64,10 +73,16 @@ def new_ilist(
6473
class PyIndexing(interp.MethodTable):
6574
@interp.impl(py.GetItem)
6675
def getitem(self, interp: AddressAnalysis, frame: interp.Frame, stmt: py.GetItem):
76+
# Integer index into the thing being indexed
6777
idx = interp.get_const_value(int, stmt.index)
78+
# The object being indexed into
6879
obj = frame.get(stmt.obj)
80+
# The `data` attributes holds onto other Address types
81+
# so we just extract that here
6982
if isinstance(obj, AddressTuple):
7083
return (obj.data[idx],)
84+
# an AddressReg is guaranteed to just have some sequence
85+
# of integers which is directly pluggable to AddressQubit
7186
elif isinstance(obj, AddressReg):
7287
return (AddressQubit(obj.data[idx]),)
7388
else:
@@ -147,3 +162,67 @@ def for_loop(
147162
return # if terminate is Return, there is no result
148163

149164
return loop_vars
165+
166+
167+
# Address lattice elements we can work with:
168+
## NotQubit (bottom), AnyAddress (top)
169+
170+
## AddressTuple -> data: tuple[Address, ...]
171+
### Recursive type, could contain itself or other variants
172+
### This pops up in cases where you can have an IList/Tuple
173+
### That contains elements that could be other Address types
174+
175+
## AddressReg -> data: Sequence[int]
176+
### specific to creation of a register of qubits
177+
178+
## AddressQubit -> data: int
179+
### Base qubit address type
180+
181+
182+
@squin.wire.dialect.register(key="qubit.address")
183+
class SquinWireMethodTable(interp.MethodTable):
184+
185+
@interp.impl(squin.wire.Unwrap)
186+
def unwrap(
187+
self,
188+
interp_: AddressAnalysis,
189+
frame: ForwardFrame[Address],
190+
stmt: squin.wire.Unwrap,
191+
):
192+
193+
origin_qubit = frame.get(stmt.qubit)
194+
195+
return (AddressWire(origin_qubit=origin_qubit),)
196+
197+
@interp.impl(squin.wire.Apply)
198+
def apply(
199+
self,
200+
interp_: AddressAnalysis,
201+
frame: ForwardFrame[Address],
202+
stmt: squin.wire.Apply,
203+
):
204+
205+
origin_qubits = tuple(
206+
[frame.get(input_elem).origin_qubit for input_elem in stmt.inputs]
207+
)
208+
new_address_wires = tuple(
209+
[AddressWire(origin_qubit=origin_qubit) for origin_qubit in origin_qubits]
210+
)
211+
return new_address_wires
212+
213+
214+
@squin.qubit.dialect.register(key="qubit.address")
215+
class SquinQubitMethodTable(interp.MethodTable):
216+
217+
# This can be treated like a QRegNew impl
218+
@interp.impl(squin.qubit.New)
219+
def new(
220+
self,
221+
interp_: AddressAnalysis,
222+
frame: ForwardFrame[Address],
223+
stmt: squin.qubit.New,
224+
):
225+
n_qubits = interp_.get_const_value(int, stmt.n_qubits)
226+
addr = AddressReg(range(interp_.next_address, interp_.next_address + n_qubits))
227+
interp_.next_address += n_qubits
228+
return (addr,)

src/bloqade/analysis/address/lattice.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,14 @@ def is_subseteq(self, other: Address) -> bool:
7272
if isinstance(other, AddressQubit):
7373
return self.data == other.data
7474
return False
75+
76+
77+
@final
78+
@dataclass
79+
class AddressWire(Address):
80+
origin_qubit: AddressQubit
81+
82+
def is_subseteq(self, other: Address) -> bool:
83+
if isinstance(other, AddressWire):
84+
return self.origin_qubit == self.origin_qubit
85+
return False

src/bloqade/qasm2/dialects/glob.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from bloqade.qasm2.parse import ast
66
from bloqade.qasm2.types import QRegType
77
from bloqade.qasm2.emit.gate import EmitQASM2Gate, EmitQASM2Frame
8-
from bloqade.analysis.schedule import DagScheduleAnalysis
8+
from bloqade.squin.analysis.schedule import DagScheduleAnalysis
99

1010
dialect = ir.Dialect("qasm2.glob")
1111

src/bloqade/qasm2/dialects/parallel.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from bloqade.qasm2.parse import ast
99
from bloqade.qasm2.types import QubitType
1010
from bloqade.qasm2.emit.gate import EmitQASM2Gate, EmitQASM2Frame
11-
from bloqade.analysis.schedule import DagScheduleAnalysis
11+
from bloqade.squin.analysis.schedule import DagScheduleAnalysis
1212

1313
dialect = ir.Dialect("qasm2.parallel")
1414

src/bloqade/qasm2/dialects/uop/schedule.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from kirin import interp
22
from kirin.analysis import ForwardFrame
33

4-
from bloqade.analysis.schedule import DagScheduleAnalysis
4+
from bloqade.squin.analysis.schedule import DagScheduleAnalysis
55

66
from . import stmts
77
from ._dialect import dialect

src/bloqade/qasm2/passes/parallel.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@
2020
)
2121
from kirin.analysis import const
2222

23-
from bloqade.analysis import address, schedule
23+
from bloqade.analysis import address
2424
from bloqade.qasm2.rewrite import (
2525
MergePolicyABC,
2626
ParallelToUOpRule,
2727
RaiseRegisterRule,
2828
UOpToParallelRule,
2929
SimpleOptimalMergePolicy,
3030
)
31+
from bloqade.squin.analysis import schedule
3132

3233

3334
@dataclass

src/bloqade/qasm2/rewrite/uop_to_parallel.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from bloqade.analysis import address
1111
from bloqade.qasm2.dialects import uop, core, parallel
12-
from bloqade.analysis.schedule import StmtDag
12+
from bloqade.squin.analysis.schedule import StmtDag
1313

1414

1515
class MergePolicyABC(abc.ABC):

src/bloqade/squin/analysis/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)