Hello,

On 08/12/2014 05:32 PM, Robert Jordens wrote:
> Quoting from the last meeting's minutes, the notion of a multiplication
> breaks down at least in the following three cases:
> 
>>   * does not help for calibrated quantities (non-linear
>>     calibration of a dac)
>>
>>   * does not help for non-constant steps (floating point
>>     pdq2 time)
>>
>>   * does not help for timings with physical latencies (different rising
>>     and falling edge latencies of an AOM due to RF amps etc)
> 
> simply because the conversion between physical and device units is not
> multiplicative (+ quantization). There are offsets and non-linearities.

Yes. I was imagining one could use the smallest possible step as native
unit in those special cases (but are they really special, or are most
devices like that?). Of course, this requires an additional mechanism
when exactness is required.

> -ESYNTAX. Do you mean
> @short_units(frequency=make_frequency_mapping(1000), duration=..)
> def pulse(self, frequency, duration):
>    ...
> ?

That would work too, but there is a bit of duplicate typing for the
parameter names.

>> One problem with this system occurs when a function passes one of its
>> parameters to different devices that potentially use different drivers
>> and unit mappings, e.g:
>> def pulse2(self, f):
>>   self.dev_a.pulse(f)
>>   self.dev_b.pulse(f)
>> Parameter annotations can help here as well; the user could write:
>> @short_units
>> def pulse2(self, f: ("dev_a.units", "dev_b.units")):
>> and the compiler checks at compile time that self.dev_a.units and
>> self.dev_b.units are equal.
> 
> The syntax is counterintuitive. A MHz is a MHz is a MHz. An intuitive
> thing would be dds_a.ftw or core.cycle units.
> 
> The @short_units stuff is not needed as physical units are the right
> thing to use here if coercion is implicit.
> 
>> Of course, if the user prefers convenience over accuracy, they can also
>> integrate rounding into pulse2:
>> def pulse2(self, f_in_MHz):
>>   self.dev_a.pulse(round(f_in_MHz*MHz))
>>   self.dev_b.pulse(round(f_in_MHz*MHz))
> 
> Should that read f_in_MHz*self.dev_a.MHz etc?

No - the system would use the correct MHz based on the parameter
annotation of dev_x.pulse.

Since Python does not provide namespaces that are local to function
parameters, the way this can be implemented in the regular Python
interpreter is that the MHz "abstract unit" object redefines all
operators (including __round__) so that the full expression is kept
(similar to Migen signals) before it is evaluated e.g. through the
@short_units decorator. Of course, a drawback of this approach is that
things will break if complex functions that are meant to work with
numbers are applied to abstract units.

> class Core:
>     cycle = Unit()
>     freq = 80*MHz
> 
>     @kernel
>     def delay_cycles(self, n):
>         # ...
> 
>     @force_fold
>     def coerce(self, v, to=None):
>         if isintance(v, to):
>             return v
>         if isinstance(v, ns.base_unit):
>             if to is None:
>                 to = self.cycle
>             return round(v*self.freq)*to
>         if ...
> 
>     @force_fold
>     def delay(self, t):
>         t = self.coerce(t, to=self.cycle)
>         self.delay_cycles(t.value)
> 
> Use:
> 
> n = core.coerce(1.2345*ns) # [n] = core.cycle
> for i in range(1000):
>     core.delay(n)
> f = dds.coerce(345*MHz)
> t = dds.coerce(core.coerce(1000*n, to=ns))
> phi = dds.coerce(f*t, to=rad) # [f*t] = dds.ftw*dds.cycle
> dds.phase(pi + phi) # implicit coercion to [phi'] = dds.ptw
> 
> in the worst case if necessary.

Ok. I'll see how this can be integrated into a good type system for the
compiler. Another advantage of the driver-defined units is that they
evaluate to numbers right away and then operations such as specifying if
a physical quantity should be stored on 32 or 64 bits boil down to the
number case.

> In virtually all cases rounding errors are to be ignored and accepted.
> For the vast majority of numbers that occur in our experiments, we
> assume and expect implicit rounding (parameters, scan variables, fit
> results, measurements).

> I like the basic units system including physical and device units but
> the conversion/coercion should generally be a function and rounding
> should be automatic and the silent default.

Ack.

Sébastien

_______________________________________________
ARTIQ mailing list
https://ssl.serverraum.org/lists/listinfo/artiq
Migen/MiSoC: please use de...@lists.m-labs.hk instead.

Reply via email to