bloqade_lanes_bytecode_core/bytecode/
instruction.rs1use super::opcode::{
2 ArrayInstCode, AtomArrangementInstCode, CpuInstCode, DetectorObservableInstCode, DeviceCode,
3 LaneConstInstCode, MeasurementInstCode, QuantumGateInstCode, pack_opcode,
4};
5
6#[derive(Debug, Clone, Copy, PartialEq)]
8pub enum CpuInstruction {
9 ConstFloat(f64),
11 ConstInt(i64),
13 Pop,
15 Dup,
17 Swap,
19 Return,
21 Halt,
23}
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum LaneConstInstruction {
28 ConstLoc(u32),
30 ConstLane(u32, u32),
32 ConstZone(u32),
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub enum AtomArrangementInstruction {
39 InitialFill { arity: u32 },
41 Fill { arity: u32 },
43 Move { arity: u32 },
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub enum QuantumGateInstruction {
50 LocalR { arity: u32 },
52 LocalRz { arity: u32 },
54 GlobalR,
56 GlobalRz,
58 CZ,
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub enum MeasurementInstruction {
65 Measure { arity: u32 },
67 AwaitMeasure,
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub enum ArrayInstruction {
74 NewArray { type_tag: u8, dim0: u16, dim1: u16 },
76 GetItem { ndims: u16 },
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub enum DetectorObservableInstruction {
83 SetDetector,
85 SetObservable,
87}
88
89#[derive(Debug, Clone, Copy, PartialEq)]
94pub enum Instruction {
95 Cpu(CpuInstruction),
97 LaneConst(LaneConstInstruction),
99 AtomArrangement(AtomArrangementInstruction),
101 QuantumGate(QuantumGateInstruction),
103 Measurement(MeasurementInstruction),
105 Array(ArrayInstruction),
107 DetectorObservable(DetectorObservableInstruction),
109}
110
111impl Instruction {
112 pub fn opcode(&self) -> u16 {
114 match self {
115 Instruction::Cpu(cpu) => {
116 let inst = match cpu {
117 CpuInstruction::ConstFloat(_) => CpuInstCode::ConstFloat as u8,
118 CpuInstruction::ConstInt(_) => CpuInstCode::ConstInt as u8,
119 CpuInstruction::Pop => CpuInstCode::Pop as u8,
120 CpuInstruction::Dup => CpuInstCode::Dup as u8,
121 CpuInstruction::Swap => CpuInstCode::Swap as u8,
122 CpuInstruction::Return => CpuInstCode::Return as u8,
123 CpuInstruction::Halt => CpuInstCode::Halt as u8,
124 };
125 pack_opcode(DeviceCode::Cpu as u8, inst)
126 }
127 Instruction::LaneConst(lc) => {
128 let inst = match lc {
129 LaneConstInstruction::ConstLoc(_) => LaneConstInstCode::ConstLoc as u8,
130 LaneConstInstruction::ConstLane(_, _) => LaneConstInstCode::ConstLane as u8,
131 LaneConstInstruction::ConstZone(_) => LaneConstInstCode::ConstZone as u8,
132 };
133 pack_opcode(DeviceCode::LaneConstants as u8, inst)
134 }
135 Instruction::AtomArrangement(aa) => {
136 let inst = match aa {
137 AtomArrangementInstruction::InitialFill { .. } => {
138 AtomArrangementInstCode::InitialFill as u8
139 }
140 AtomArrangementInstruction::Fill { .. } => AtomArrangementInstCode::Fill as u8,
141 AtomArrangementInstruction::Move { .. } => AtomArrangementInstCode::Move as u8,
142 };
143 pack_opcode(DeviceCode::AtomArrangement as u8, inst)
144 }
145 Instruction::QuantumGate(qg) => {
146 let inst = match qg {
147 QuantumGateInstruction::LocalR { .. } => QuantumGateInstCode::LocalR as u8,
148 QuantumGateInstruction::LocalRz { .. } => QuantumGateInstCode::LocalRz as u8,
149 QuantumGateInstruction::GlobalR => QuantumGateInstCode::GlobalR as u8,
150 QuantumGateInstruction::GlobalRz => QuantumGateInstCode::GlobalRz as u8,
151 QuantumGateInstruction::CZ => QuantumGateInstCode::CZ as u8,
152 };
153 pack_opcode(DeviceCode::QuantumGate as u8, inst)
154 }
155 Instruction::Measurement(m) => {
156 let inst = match m {
157 MeasurementInstruction::Measure { .. } => MeasurementInstCode::Measure as u8,
158 MeasurementInstruction::AwaitMeasure => MeasurementInstCode::AwaitMeasure as u8,
159 };
160 pack_opcode(DeviceCode::Measurement as u8, inst)
161 }
162 Instruction::Array(arr) => {
163 let inst = match arr {
164 ArrayInstruction::NewArray { .. } => ArrayInstCode::NewArray as u8,
165 ArrayInstruction::GetItem { .. } => ArrayInstCode::GetItem as u8,
166 };
167 pack_opcode(DeviceCode::Array as u8, inst)
168 }
169 Instruction::DetectorObservable(dob) => {
170 let inst = match dob {
171 DetectorObservableInstruction::SetDetector => {
172 DetectorObservableInstCode::SetDetector as u8
173 }
174 DetectorObservableInstruction::SetObservable => {
175 DetectorObservableInstCode::SetObservable as u8
176 }
177 };
178 pack_opcode(DeviceCode::DetectorObservable as u8, inst)
179 }
180 }
181 }
182
183 pub fn device_code(&self) -> DeviceCode {
185 match self {
186 Instruction::Cpu(_) => DeviceCode::Cpu,
187 Instruction::LaneConst(_) => DeviceCode::LaneConstants,
188 Instruction::AtomArrangement(_) => DeviceCode::AtomArrangement,
189 Instruction::QuantumGate(_) => DeviceCode::QuantumGate,
190 Instruction::Measurement(_) => DeviceCode::Measurement,
191 Instruction::Array(_) => DeviceCode::Array,
192 Instruction::DetectorObservable(_) => DeviceCode::DetectorObservable,
193 }
194 }
195}
196
197#[cfg(test)]
198mod tests {
199 use super::*;
200
201 #[test]
202 fn test_opcode_cpu() {
203 assert_eq!(
204 Instruction::Cpu(CpuInstruction::ConstFloat(1.0)).opcode(),
205 0x0300
206 );
207 assert_eq!(
208 Instruction::Cpu(CpuInstruction::ConstInt(1)).opcode(),
209 0x0200
210 );
211 assert_eq!(Instruction::Cpu(CpuInstruction::Pop).opcode(), 0x0500);
212 assert_eq!(Instruction::Cpu(CpuInstruction::Dup).opcode(), 0x0400);
213 assert_eq!(Instruction::Cpu(CpuInstruction::Swap).opcode(), 0x0600);
214 assert_eq!(Instruction::Cpu(CpuInstruction::Return).opcode(), 0x6400);
215 assert_eq!(Instruction::Cpu(CpuInstruction::Halt).opcode(), 0xFF00);
216 }
217
218 #[test]
219 fn test_opcode_lane_constants() {
220 assert_eq!(
221 Instruction::LaneConst(LaneConstInstruction::ConstLoc(0)).opcode(),
222 0x000F
223 );
224 assert_eq!(
225 Instruction::LaneConst(LaneConstInstruction::ConstLane(0, 0)).opcode(),
226 0x010F
227 );
228 assert_eq!(
229 Instruction::LaneConst(LaneConstInstruction::ConstZone(0)).opcode(),
230 0x020F
231 );
232 }
233
234 #[test]
235 fn test_opcode_atom_arrangement() {
236 assert_eq!(
237 Instruction::AtomArrangement(AtomArrangementInstruction::InitialFill { arity: 1 })
238 .opcode(),
239 0x0010
240 );
241 assert_eq!(
242 Instruction::AtomArrangement(AtomArrangementInstruction::Fill { arity: 1 }).opcode(),
243 0x0110
244 );
245 assert_eq!(
246 Instruction::AtomArrangement(AtomArrangementInstruction::Move { arity: 1 }).opcode(),
247 0x0210
248 );
249 }
250
251 #[test]
252 fn test_opcode_quantum_gate() {
253 assert_eq!(
254 Instruction::QuantumGate(QuantumGateInstruction::LocalR { arity: 1 }).opcode(),
255 0x0011
256 );
257 assert_eq!(
258 Instruction::QuantumGate(QuantumGateInstruction::LocalRz { arity: 1 }).opcode(),
259 0x0111
260 );
261 assert_eq!(
262 Instruction::QuantumGate(QuantumGateInstruction::GlobalR).opcode(),
263 0x0211
264 );
265 assert_eq!(
266 Instruction::QuantumGate(QuantumGateInstruction::GlobalRz).opcode(),
267 0x0311
268 );
269 assert_eq!(
270 Instruction::QuantumGate(QuantumGateInstruction::CZ).opcode(),
271 0x0411
272 );
273 }
274
275 #[test]
276 fn test_opcode_measurement() {
277 assert_eq!(
278 Instruction::Measurement(MeasurementInstruction::Measure { arity: 1 }).opcode(),
279 0x0012
280 );
281 assert_eq!(
282 Instruction::Measurement(MeasurementInstruction::AwaitMeasure).opcode(),
283 0x0112
284 );
285 }
286
287 #[test]
288 fn test_opcode_array() {
289 assert_eq!(
290 Instruction::Array(ArrayInstruction::NewArray {
291 type_tag: 0,
292 dim0: 10,
293 dim1: 20
294 })
295 .opcode(),
296 0x0013
297 );
298 assert_eq!(
299 Instruction::Array(ArrayInstruction::GetItem { ndims: 2 }).opcode(),
300 0x0113
301 );
302 }
303
304 #[test]
305 fn test_opcode_detector_observable() {
306 assert_eq!(
307 Instruction::DetectorObservable(DetectorObservableInstruction::SetDetector).opcode(),
308 0x0014
309 );
310 assert_eq!(
311 Instruction::DetectorObservable(DetectorObservableInstruction::SetObservable).opcode(),
312 0x0114
313 );
314 }
315
316 #[test]
317 fn test_device_code() {
318 assert_eq!(
319 Instruction::Cpu(CpuInstruction::Halt).device_code(),
320 DeviceCode::Cpu
321 );
322 assert_eq!(
323 Instruction::LaneConst(LaneConstInstruction::ConstLoc(0)).device_code(),
324 DeviceCode::LaneConstants
325 );
326 assert_eq!(
327 Instruction::AtomArrangement(AtomArrangementInstruction::Fill { arity: 1 })
328 .device_code(),
329 DeviceCode::AtomArrangement
330 );
331 assert_eq!(
332 Instruction::QuantumGate(QuantumGateInstruction::CZ).device_code(),
333 DeviceCode::QuantumGate
334 );
335 assert_eq!(
336 Instruction::Measurement(MeasurementInstruction::AwaitMeasure).device_code(),
337 DeviceCode::Measurement
338 );
339 assert_eq!(
340 Instruction::Array(ArrayInstruction::GetItem { ndims: 1 }).device_code(),
341 DeviceCode::Array
342 );
343 assert_eq!(
344 Instruction::DetectorObservable(DetectorObservableInstruction::SetDetector)
345 .device_code(),
346 DeviceCode::DetectorObservable
347 );
348 }
349}