forked from M-Labs/artiq
1
0
Fork 0

coredevice.dds: work around the round(numpy.float64()) snafu.

This commit is contained in:
whitequark 2016-11-20 09:48:49 +00:00
parent d7f4397924
commit abf2b32b20
2 changed files with 32 additions and 5 deletions

View File

@ -112,7 +112,7 @@ class _DDSGeneric:
"""Returns the frequency tuning word corresponding to the given """Returns the frequency tuning word corresponding to the given
frequency. frequency.
""" """
return round(int64(2)**32*frequency/self.core_dds.sysclk) return round(float(int64(2)**32*frequency/self.core_dds.sysclk))
@portable(flags=["fast-math"]) @portable(flags=["fast-math"])
def ftw_to_frequency(self, ftw): def ftw_to_frequency(self, ftw):
@ -125,7 +125,7 @@ class _DDSGeneric:
def turns_to_pow(self, turns): def turns_to_pow(self, turns):
"""Returns the phase offset word corresponding to the given phase """Returns the phase offset word corresponding to the given phase
in turns.""" in turns."""
return round(turns*2**self.pow_width) return round(float(turns*2**self.pow_width))
@portable(flags=["fast-math"]) @portable(flags=["fast-math"])
def pow_to_turns(self, pow): def pow_to_turns(self, pow):
@ -136,7 +136,7 @@ class _DDSGeneric:
@portable(flags=["fast-math"]) @portable(flags=["fast-math"])
def amplitude_to_asf(self, amplitude): def amplitude_to_asf(self, amplitude):
"""Returns amplitude scale factor corresponding to given amplitude.""" """Returns amplitude scale factor corresponding to given amplitude."""
return round(amplitude*0x0fff) return round(float(amplitude*0x0fff))
@portable(flags=["fast-math"]) @portable(flags=["fast-math"])
def asf_to_amplitude(self, asf): def asf_to_amplitude(self, asf):

View File

@ -10,7 +10,7 @@ A number of Python features can be used inside a kernel for compilation and exec
* Booleans * Booleans
* 32-bit signed integers (default size) * 32-bit signed integers (default size)
* 64-bit signed integers (use ``int(n, width=64)`` to convert) * 64-bit signed integers (use ``numpy.int64`` to convert)
* Double-precision floating point numbers * Double-precision floating point numbers
* Lists of any supported types * Lists of any supported types
* User-defined classes, with attributes of any supported types (attributes that are not used anywhere in the kernel are ignored) * User-defined classes, with attributes of any supported types (attributes that are not used anywhere in the kernel are ignored)
@ -36,7 +36,7 @@ The Python types correspond to ARTIQ type annotations as follows:
+-------------+-------------------------+ +-------------+-------------------------+
| bool | TBool | | bool | TBool |
+-------------+-------------------------+ +-------------+-------------------------+
| int | TInt32, TInt64 | | int | TInt32 or TInt64 |
+-------------+-------------------------+ +-------------+-------------------------+
| float | TFloat | | float | TFloat |
+-------------+-------------------------+ +-------------+-------------------------+
@ -46,6 +46,33 @@ The Python types correspond to ARTIQ type annotations as follows:
+-------------+-------------------------+ +-------------+-------------------------+
| range | TRange32, TRange64 | | range | TRange32, TRange64 |
+-------------+-------------------------+ +-------------+-------------------------+
| numpy.int32 | TInt32 |
+-------------+-------------------------+
| numpy.int64 | TInt64 |
+-------------+-------------------------+
| numpy.float64 | TFloat |
+-------------+-------------------------+
Pitfalls
--------
The ARTIQ compiler accepts *nearly* a strict subset of Python 3. However, by necessity there
is a number of differences that can lead to bugs.
Arbitrary-length integers are not supported at all on the core device; all integers are
either 32-bit or 64-bit. This especially affects calculations that result in a 32-bit signed
overflow; if the compiler detects a constant that doesn't fit into 32 bits, the entire expression
will be upgraded to 64-bit arithmetics, however if all constants are small, 32-bit arithmetics
will be used even if the result will overflow. Overflows are not detected.
The result of calling the builtin ``round`` function is different when used with
the builtin ``float`` type and the ``numpy.float64`` type on the host interpreter; ``round(1.0)``
returns an integer value 1, whereas ``round(numpy.float64(1.0))`` returns a floating point value
``numpy.float64(1.0)``. Since both ``float`` and ``numpy.float64`` are mapped to
the builtin ``float`` type on the core device, this can lead to problems in functions marked
``@portable``; the workaround is to explicitly cast the argument of ``round`` to ``float``:
``round(float(numpy.float64(1.0)))`` returns an integer on the core device as well as on the host
interpreter.
Asynchronous RPCs Asynchronous RPCs
----------------- -----------------