-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Port standard instructions to Rust. #13486
base: main
Are you sure you want to change the base?
Conversation
This way, we can also use this enum to tag the Python classes.
I'm concerned that the I feel like the bitshift and masking operations could be extended over the whole u64, and that'll all automatically work on BE and 32-bit systems, especially with the size of The |
I guess my main point is this: the 64-bit
Introducing If you want a shade more encapsulation than my loose struct PayloadLocation<T: SomeBytemuckOrCustomTrait> {
mask: u64,
shift: u32,
datatype: PhantomData<T>,
}
impl PayloadLocation {
// Note we _mustn't_ accept `PackedOperation` until we've got a valid one,
// because holding a `PackedOperation` implies ownership over its stored
// pointer, and it mustn't `Drop` or attempt to interpret partial data.
#[inline]
fn store(&self, src: T, target: u64) -> u64 {
let src: u64 = bytemuck::cast(src);
target | ((src << self.shift) & self.mask)
}
#[inline]
fn load(&self, target: u64) -> T {
bytemuck::cast((target & self.mask) >> self.shift)
}
}
const PACKED_OPERATION_DISCRIMINANT = PayloadLocation { mask: 0b111, shift: 0 };
const STANDARD_GATE_DISCRIMINANT = PayloadLocation { mask: 0bff << 3, shift: 3 };
const POINTER_PAYLOAD = PayloadLocation { mask: usize::MAX as u64 & 0b000, shift: 0 };
// and so on (Bear in mind I just typed that raw without trying it, and I didn't think all that hard about what the trait bound should be.) If everything's inlined and constant, the compiler absolutely should be able to compile out 32 bit shifts and all-ones masks into partial register reads/loads itself, so there oughtn't to be any overhead. |
Summary
Adds a new Rust enum
StandardInstruction
representation for standard instructions (i.e.Barrier
,Delay
,Measure
andReset
) and updates the encoding ofPackedOperation
to support storing it compactly at rest.The size of a
PackedOperation
has now been anchored to always be 64 bits, even on 32-bit systems. This is necessary to encode the data payload of standard instructions likeBarrier
andDelay
. See the docstrings withinpacked_instruction.rs
for details.Details and comments
The implementation works very similarly to what we currently do for
StandardGate
, but with a bit of extra consideration for an additional data payload used by variadic/template instructions likeBarrier
andDelay
.Similarly to
StandardGate
, the newly addedStandardInstruction
enum serves as the first-class Rust interface for working with standard instructions. The existingOperationRef
enum returned byPackedOperation::view
has a new variantStandardInstruction
which exposes this.Unlike
StandardGate
,StandardInstruction
is not apyclass
because it is not directly used to tag instructions as standard in our Python class definitions. Instead, the simple integral enumStandardInstructionType
is used as the tag, andOperationFromPython::extract_bound
further queries the incoming Python object for variadic/template data when building the completeStandardInstruction
.Encoding
The
PackedOperation
encoding has been updated as follows:PackedOperation
is now always 64 bits wide even on 32 bit systems, and is technically aunion
, viewed as either two sequential 32 bit words or a platform widthusize
, reinterpreted as a pointer.StandardInstruction
.Todo: