openquantumhardware / qick

QICK: Quantum Instrumentation Control Kit
MIT License
177 stars 74 forks source link

Adding a .simulate() to the AveragerProgram class? #229

Open tristanlorriaux opened 5 months ago

tristanlorriaux commented 5 months ago

Hello there QICK team ! It's not a bug, but it's a feature (idea). I was wondering if you would think possible to add in a next update a .simulate(soccfg) method to the QICK AveragerProgram class, that would return various numpy.ndarrays for instance for each t_proc channel. Generator channel could return pulse values, readout channel could return a 0 or 1 if they are reading or not for example, plus a timestamp array? In fact I don't know if it's possible but in this idea it would be awesome ! That would help for pulse shaping for the experiment, and would allow to see 'what we send'. In any case, thank you for your incredible work, and the support you give to the package ! Best regards, Tristan from QCircuits, Lyon 🚀

meeg commented 5 months ago

Thanks - something like this would certainly be helpful, the difficulty is in how far to go with it.

At a very basic level, it's easy to add something that tells you which generators and readouts are declared in a program (you can see this yourself by peeking at prog.ro_chs and prog.gen_chs). This is "robust" in the sense that I can be quite sure that a declared readout is going to get read out. But its power is very limited.

Then, it would not be a lot of work to write something that tells you your pulse and readout times, etc. under the assumption that they can just be calculated from the ts and sync_all()s and so on. But now this is not robust - there are many things that people can do (and often do) that will break this, like delay sweeps and conditional jumps, or just bad timeline management. It's dangerous to give people a tool like this that works in simple situations but is wrong in complicated ones, and doesn't know when it is wrong - like an autopilot in a vehicle with unreliable instruments.

A real simulator would solve that problem - something that steps through the ASM code and computes what the tProcessor will do, no assumptions. But this is a bit of a project, particularly if you want it to be really correct about how many cycles it takes the tProcessor to execute each instruction etc. There has been work put into this, but in the end we have not had time to really bring it to completion. The firmware design tools have simulators like this, of course, but they don't interface well to Python.

A separate problem is that we are working on a new version of the tProcessor (which we call v2, the current one is v1) which will have a completely new ASM language and program interface. So AveragerProgram will get replaced in the next few months by something which works similarly, but different, and we are not really going to do any more substantial work on v1 (you will still be able to use v1 of course, and we will fix bugs, but we think that people will prefer to use v2).

Anyway . . . your suggestion is a good one and appreciated, and I am happy to keep talking. I think we can converge on some ideas that are both easy and useful, and we will apply them to v2.

tristanlorriaux commented 4 months ago

Hi ! Thanks for you quick answer, as usual !

At a very basic level, it's easy to add something that tells you which generators and readouts are declared in a program (you can see this yourself by peeking at prog.ro_chs and prog.gen_chs). This is "robust" in the sense that I can be quite sure that a declared readout is going to get read out. But its power is very limited.

I agree this is very a robust raw idea, but it could take a lot of development for 'not so much' results.

A separate problem is that we are working on a new version of the tProcessor (which we call v2, the current one is v1) which will have a completely new ASM language and program interface. So AveragerProgram will get replaced in the next few months by something which works similarly, but different, and we are not really going to do any more substantial work on v1 (you will still be able to use v1 of course, and we will fix bugs, but we think that people will prefer to use v2).

So the basic idea is that the new tProc ASM would give more details that would allow to write a .simulate() method more robust and easier? It's super exciting to hear this !

The idea could be to converge to this kind of pulse sequence plot you can encounter for each tProc channel used, in this package for instance: https://github.com/kaustubhmote/pulseplot/tree/master

Anyway, I'll wait for the future updates :) !

Best regards, Tristan from QCircuits, Lyon 🚀

meeg commented 4 months ago

Yep, I know what you mean . . . everyone wants the pretty pulse sequence plot! I think the short answer is that it's not possible for the current AveragerProgram because a) a very large fraction of programs are written in a way that it's not possible to easily predict what the pulse sequence will look like, and b) we're not going to do more development on the tProc v1.

But I think it's a reasonable goal for tProc v2, to have the ability to generate a pulse sequence plot as long as your program only uses the basic functions of AveragerProgramV2 (if you use custom assembly language stuff and try to predict the pulse sequence, you will get an error). I'll leave this issue open as a reminder.