@micropython.viper causes ImportError

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
DanielRossinsky
Posts: 9
Joined: Fri Jun 12, 2020 4:04 am

@micropython.viper causes ImportError

Post by DanielRossinsky » Sun Jun 21, 2020 5:18 am

The problem:
I'm trying to optimize a part of an ili9341 driver and came across an ImportError when using @micropython.viper decorator.
the code i used is as follows:

Code: Select all

class Display(object):
    self.spi = SPI(VSPI, 40000000,  sck=Pin(18), mosi=Pin(23), miso=Pin(19))
    
    @micropython.viper
    def write_data(self, data):
        self.spi.write(data)
        
    @micropython.viper #if I remove this line the Import error goes away
    def push_block(self, color: uint, length: uint):
        chunks = uint(length // 512)
        rest   = uint(length %  512)
        if chunks > 0:
            data = ptr8(ustruct.pack(">H", color) * 512)
            for _ in range(chunks):
                self.write_data(data)
        if rest > 0:
            data = ptr8(ustruct.pack(">H", color) * rest)
            self.write_data(data)
Things i noticed:
As you can see I tried adding hints for viper with uint and ptr8 however the error remains with and without those.

full error:
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
ImportError: cannot import name Display

The ImportError only happens when I use the @micropython.viper decorator on push_block, any ideas why this happens ? and is it fixable ?

Note: I still want to use @micropython.viper decorator on push_block

User avatar
tve
Posts: 216
Joined: Wed Jan 01, 2020 10:12 pm
Location: Santa Barbara, CA
Contact:

Re: @micropython.viper causes ImportError

Post by tve » Sun Jun 21, 2020 7:15 am

Can you please provide a complete example to reproduce the problem? I tried the following on an esp32 running MP 1.12:

Code: Select all

> cat test.py
from machine import SPI, VSPI, Pin
class Display(object):
    self.spi = SPI(VSPI, 40000000,  sck=Pin(18), mosi=Pin(23), miso=Pin(19))

    @micropython.viper
    def write_data(self, data):
        self.spi.write(data)

    @micropython.viper #if I remove this line the Import error goes away
    def push_block(self, color: uint, length: uint):
        chunks = uint(length // 512)
        rest   = uint(length %  512)
        if chunks > 0:
            data = ptr8(ustruct.pack(">H", color) * 512)
            for _ in range(chunks):
                self.write_data(data)
        if rest > 0:
            data = ptr8(ustruct.pack(">H", color) * rest)
            self.write_data(data)
> pyboard ./test.py
Traceback (most recent call last):
  File "<stdin>", line 11, in push_block
ViperTypeError: can't do binary op between 'uint' and 'int'
Looks like the issue is `length // 512`...

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: @micropython.viper causes ImportError

Post by pythoncoder » Sun Jun 21, 2020 8:31 am

Viper seems to barf on any math operations on uints:

Code: Select all

@micropython.viper
def foo(x:uint) -> uint:
    return x + uint(9)
produces

Code: Select all

ViperTypeError: can't do binary op between 'uint' and 'uint'
I tried various operators with the same result each time. I've raised an issue.

@DanielRossinsky As a workround I suggest you try using ints.
Peter Hinch
Index to my micropython libraries.

DanielRossinsky
Posts: 9
Joined: Fri Jun 12, 2020 4:04 am

Re: @micropython.viper causes ImportError

Post by DanielRossinsky » Sun Jun 21, 2020 1:29 pm

@pythoncoder As I mentioned it doesn't matter if I include any hints for viper or not as it will throw an ImportError either way.
However, I did make some progress! It now works with @micropython.native yet still throws an ImportError if i try to use @micropython.viper any idea ?

Note: I decided not to use any hints this time and got rid of // and %.

Code: Select all

    @micropython.native
    def _push_color(self, color, length):
       chunks, rest = divmod(length, 512)
       if chunks:
           data = ustruct.pack(">H", color) * 512
           for count in range(chunks):
               self._write_data(data)
       if rest:
           data = ustruct.pack(">H", color) * rest
           self._write_data(data)

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: @micropython.viper causes ImportError

Post by pythoncoder » Mon Jun 22, 2020 5:41 am

This bug is being fixed. You can test the solution now if you know how to grab a PR and build the firmware, otherwise wait until the fix is merged and download a daily build.
Peter Hinch
Index to my micropython libraries.

Post Reply