« Vivado Constraints Wizardによるクロック・入出力制約の作成 | トップページ | PYNQ-Z1のOverlay読み込みとPythonからのFPGA PLの制御(2) »

PYNQ-Z1のOverlay読み込みとPythonからのFPGA PLの制御

PYNQ-Z1はZYBOとよく似たZYNQ SoCを使ったFPGAボードですが、Pythonを使ってLinuxからFPGAのリソースにアクセスできることが特徴です。PYNQではFPGAのConfiguration Data (bitsteam) をOverlayと呼んでおり、標準でPYNQのI/Oやビデオ関係の処理ができるOverlayが提供されているのですが、ドキュメントを読んでいると、カスタムOverlayも作成できるとあります。

カスタムOverlayを作ってそれを動的にダウンロードできれば、FPGAのReconfigurableな利点を生かして、必要に応じてI/Oピンの割り当てを変更したり、さらには必要に応じてハードで処理する機能(画像処理など)を組み込めるという、RaspberryPiなどのマイコンボードでは絶対に真似ねできない、高い拡張性とPythonによる容易なプログラミングができるということになります。

本当にカスタムOverlayが動的にダウンロードできるのか(Linuxを動かしながらFPGAを動的にconfig変更できるのか)Lチカで実験してみました。

OverlayダウンロードとPythonからの制御の仕組みを調べる

PYNQはSMBのサーバーとして動いているため、WindowsのFile ExplorerやmacOSのFinderで/home/xilinx配下のディレクトリーやファイルにアクセスが可能です。

QYNQ Folder

pl.pyファイルの中にあるbitstreamクラスがOverlayのダウンロードに関係していそうです。ファイルの中身を以下に示します。 

class Bitstream(PL):
    """This class instantiates a programmable logic bitstream.
    
    Attributes
    ----------
    bitfile_name : str
        The absolute path of the bitstream.
    timestamp : str
        Timestamp when loading the bitstream. Format:
        year, month, day, hour, minute, second, microsecond
        
    """
    
    def __init__(self, bitfile_name):
        """Return a new Bitstream object.
        
        Users can either specify an absolute path to the bitstream file
        (e.g. '/home/xilinx/src/pynq/bitstream/base.bit'),
        or only a relative path.
        (e.g. 'base.bit').
        
        Note
        ----
        self.bitstream always stores the absolute path of the bitstream.
        
        Parameters
        ----------
        bitfile_name : str
            The bitstream absolute path or name as a string.
            
        """
        super().__init__()
        
        if not isinstance(bitfile_name, str):
            raise TypeError("Bitstream name has to be a string.")
        
        if os.path.isfile(bitfile_name):
            self.bitfile_name = bitfile_name
        elif os.path.isfile(general_const.BS_SEARCH_PATH + bitfile_name):
            self.bitfile_name = general_const.BS_SEARCH_PATH + bitfile_name
        else:
            raise IOError('Bitstream file {} does not exist.'\
                            .format(bitfile_name))
            
        self.timestamp = ''

    def download(self):
        """The method to download the bitstream onto PL.
        
        Note
        ----
        The class variables held by the singleton PL will also be updated.

        Parameters
        ----------
        None

        Returns
        -------
        None
            
        """
        # Compose bitfile name, open bitfile
        with open(self.bitfile_name, 'rb') as f:
            buf = f.read()
        
        # Set is_partial_bitfile device attribute to 0
        with open(general_const.BS_IS_PARTIAL, 'w') as fd:
            fd.write('0')
        
        # Write bitfile to xdevcfg device
        with open(general_const.BS_XDEVCFG, 'wb') as f:
            f.write(buf)
        
        t = datetime.now()
        self.timestamp = "{}/{}/{} {}:{}:{} +{}".format(t.year,t.month,t.day,\
                                t.hour,t.minute,t.second,t.microsecond)
        
        # Update PL information
        PL._client_request()
        PL._bitfile_name = self.bitfile_name
        PL._timestamp = self.timestamp
        PL._ip_dict = {}
        PL._gpio_dict = {}
        PL._server_update()

64〜65行目でbitsteamのデーターを読み込んで、72〜73行目で「general_const.BS_XDEVCFG」ファイルに書き込んでいます。general_const.BS_XDEVCFGの実態は、"/dev/xdevcfg"というデバイスファイルです。どうやらこのデバイスファイルに書き込みを行うことによってOverlay (bitstream) のダウンロードができるようです。

FPGAの制御(FPGAのレジスタへの書き込み)はmmio.pyのMMIOクラスを使って、/dev/memデバイスファイル経由でメモリー空間にマップされたFPGAのレジスタにアクセスしているようです。Pythonのコードは以下になります。 

class MMIO:
    """ This class exposes API for MMIO read and write.

    Attributes
    ----------
    virt_base : int
        The address of the page for the MMIO base address.
    virt_offset : int
        The offset of the MMIO base address from the virt_base.
    base_addr : int
        The base address, not necessarily page aligned.
    length : int
        The length in bytes of the address range.
    debug : bool
        Turn on debug mode if it is True.
    mmap_file : file
        Underlying file object for MMIO mapping
    mem : mmap
        An mmap object created when mapping files to memory.
    array : numpy.ndarray
        A numpy view of the mapped range for efficient assignment

    """

    def __init__(self, base_addr, length=4, debug=False):
        """Return a new MMIO object.

        Parameters
        ----------
        base_addr : int
            The base address of the MMIO.
        length : int
            The length in bytes; default is 4.
        debug : bool
            Turn on debug mode if it is True; default is False.

        """
        if base_addr < 0 or length < 0:
            raise ValueError("Negative offset or negative length.")

        euid = os.geteuid()
        if euid != 0:
            raise EnvironmentError('Root permissions required.')

        # Align the base address with the pages
        self.virt_base = base_addr & ~(mmap.PAGESIZE - 1)

        # Calculate base address offset w.r.t the base address
        self.virt_offset = base_addr - self.virt_base

        # Storing the base address and length
        self.base_addr = base_addr
        self.length = length

        self.debug = debug
        self._debug('MMIO(address, size) = ({0:x}, {1:x} bytes).',
                    self.base_addr, self.length)

        # Open file and mmap
        self.mmap_file = os.open(general_const.MMIO_FILE_NAME,
                                 os.O_RDWR | os.O_SYNC)

        self.mem = mmap.mmap(self.mmap_file, (self.length + self.virt_offset),
                             mmap.MAP_SHARED,
                             mmap.PROT_READ | mmap.PROT_WRITE,
                             offset=self.virt_base)

        self.array = np.frombuffer(self.mem, np.uint32,
                                   length >> 2, self.virt_offset)

    def __del__(self):
        """Destructor to ensure mmap file is closed
        """
        os.close(self.mmap_file)

    def read(self, offset=0, length=4):
        """The method to read data from MMIO.

        Parameters
        ----------
        offset : int
            The read offset from the MMIO base address.
        length : int
            The length of the data in bytes.

        Returns
        -------
        list
            A list of data read out from MMIO

        """
        if not length == 4:
            raise ValueError("MMIO currently only supports 4-byte reads.")
        if offset < 0 or length < 0:
            raise ValueError("Negative offset or negative length.")
        idx = offset >> 2
        if idx << 2 != offset:
            raise MemoryError('Read operation unaligned.')

        self._debug('Reading {0} bytes from offset {1:x}',
                    length, offset)

        # Read data out
        return int(self.array[idx])

    def write(self, offset, data):
        """The method to write data to MMIO.

        Parameters
        ----------
        offset : int
            The write offset from the MMIO base address.
        data : int / bytes
            The integer(s) to be written into MMIO.

        Returns
        -------
        None

        """
        if offset < 0:
            raise ValueError("Negative offset.")

        idx = offset >> 2
        if idx << 2 != offset:
            raise MemoryError('Write operation not aligned.')

        if type(data) is int:
            self._debug('Writing 4 bytes to offset {0:x}: {1:x}',
                        offset, data)
            self.array[idx] = np.uint32(data)
        elif type(data) is bytes:
            length = len(data)
            num_words = length >> 2
            if num_words << 2 != length:
                raise MemoryError('Need an integer number of words')
            buf = np.frombuffer(data, np.uint32, num_words, 0)
            self.array[offset:offset + num_words] = buf
        else:
            raise ValueError("Data type must be int or bytes.")

60行目でopenしている、general_const.MMIO_FILE_NAMEの実態が/dev/memで、63〜66行目でmmapを使ってFPGAのレジスタをマッピングしています。

試験用のbitstreamを作る

試験用に、ZYNQ PSとGPIOのみの最小構成のシステムを作り、GPIOにLED0〜LED3を接続しました。

MyLED Block Design

ZYNQ PLは、Diligent社PYNQサイトのZynq Presetからダウンロードした”pynq_revC.tcl”を使ってPLの設定を行います(Apply Configuration..でtclファイルを指定する)。さらに、ZYNQの構成でMAXI-GP0ポートを有効にします。次にAXI-GPIOを起こして接続したものが上記のブロックデザインになります。

合成・インプリ・ビットストリームの生成を行い、bitstreamをled.bitというファイル名で、PYNQに書き込みます。

動作確認

まずは、標準のOverlayを使ってRGB LEDをLチカするPyhonコードを動かしてみます。Jupyter Notebookは以下の通りです。

Color LED notebook

RGB LEDのLチカが動きました。

次に、一旦動いているNotebookをshutdownします(これを行わずに、Overlayを再ダウンロードするとLinuxが固まる時があります)。

Stop RGB LED

次に、先ほど作ったbitsteamをOverlayとしてダウンロードし、LEDを点滅させるコードを書いてみました。bitstreamクラスやMMIOクラスの低レベル処理をそのまま使っています。

MyLED blink2

Runすると、LED0〜LED3が点滅しました!!

このコードでは、GPIO0のアドレス、0x41200000に対して直接書き込みを行うことによってLEDの点滅を行なっています。非常に低レベルな処理で記述していますが、本来はこれを上位のクラスでラッピングして使いやすいオブジェクトとして見せることになります(今回は、上位クラスの作成はサボっています)。

後書き

今回の実験の成果を3月4日のPYNQ祭りでLTします。Lチカだけではつまらないので、もう少し機能を追加した内容で発表できればと思っています(2月は仕事でドタバタしそうなので、どこまでできるかなのですが)。前段の普通の発表や、@cobac さんのLTと被りそうな気がしますがその際はご容赦を...

PYNQで動的にFPGAをコンフィグして使用することが可能であることが分かりました。これは結構画期的だと思います。Arduinoやmbedの様にオープンソース(ハード?)のOverlayがライブラリとして流通するようになると面白いと思います。

« Vivado Constraints Wizardによるクロック・入出力制約の作成 | トップページ | PYNQ-Z1のOverlay読み込みとPythonからのFPGA PLの制御(2) »

FPGA」カテゴリの記事

PYNQ」カテゴリの記事

コメント

xilinxボードではお世話になっています。 高橋と申します。pynq-Z1に最新のimgをSDに入れた後でjupiter notebookがネット接続で起動できないのでとりあえず
HDMIモニターを動かしubuntuのデスクトップ環境で作業するため以下のpythonコードを実行したのですがHDMI定義がないとのエラーになりました。
https://pynq.readthedocs.io/en/v1.4/9_base_overlay_video.htmlに定義コード例があるのですが from pynq import Overlay from pynq.drivers.video import HDMI
の定義部で同様にpynq.drivers.videoがないとのエラーになりました。
Overlayについて知識不足のため具体的にSDのどのdirectory内でpythonコードを実行すれば良いのかお知らせ頂きたくお願いいたします。
# https://www.slideshare.net/ciniml/pynquipynq
#HDMI Initialize
hdmi = HDMI('out')
hdmi.mode(0) # 640x480x@60
hdmi.start()

# frame get
hdmi = hdmi.frame(0)
frame[x,y] = (0, 255, 255) # pixcel
hdmi.frame(0,frame)

todotaniです。
長らくPYNQを使っていませんでしたが、V2になってOverlay関連のAPIが変わったようです。
コメントで参照されているドキュメントはv1.4ですが、最新はv2.2ですので、以下のURLを見て下さい。
https://pynq.readthedocs.io/en/v2.2.1/pynq_overlays/loading_an_overlay.html

HDMI関連は以下のコードで動きました。
参照: https://pynq.readthedocs.io/en/v2.2.1/pynq_libraries/video.html

from pynq import Overlay
from pynq.lib.video import *

base = Overlay('base.bit')
hdmi_in = base.video.hdmi_in
hdmi_out = base.video.hdmi_out

HDMI I/Fを使った動作の詳細は申し訳ありませんが分かりません。

お世話になります
回答 ありがとうございます。
指摘の内容で確認しましたがコードエラーはなくなりましたが、モニターに表示されません。
今回のコードですが、SDの起動ログを表示しているPCのTeratermと同一の内容がHDMIから出力される設定ということでしょうか?
一応 ビデオからの映像もHDMI in端子に入れてみましたがこちらも表示がありません。
また以下でいただいたコードに追加しましたが結果はNGでin start raise RuntimeError("Video mode not set, channel not started") がでています。
#HDMI_out_Todotani_9_11_5.py
from pynq import Overlay
from pynq.lib.video import *
base = Overlay('base.bit')
hdmi_in = base.video.hdmi_in
hdmi_out = base.video.hdmi_out
# 2018_9_11 ===============================
#hdmi_in.state() "Could not find IP or hierarchy {} in overlay".format(key))
#hdmi_in.start() in start raise RuntimeError("Video mode not set, channel not started")
#hdmi_out = HDMI('out')
hdmi_out.start()

xilinx@MT:~/jupyter_notebooks/base$ sudo python3.6 HDMI_out_Todotani_9_11_5.py
Traceback (most recent call last):
File "HDMI_out_Todotani_9_11_5.py", line 20, in
hdmi_out.start()
File "/opt/python3.6/lib/python3.6/site-packages/pynq/lib/video.py", line 1228, in start
self._vdma.writechannel.start()
File "/opt/python3.6/lib/python3.6/site-packages/pynq/lib/video.py", line 579, in start
raise RuntimeError("Video mode not set, channel not started")
RuntimeError: Video mode not set, channel not started

HDMIの解像度の設定等追加のコードが必要かやpythonの実行direcroyなど表示されない予想原因がわかりましたらお願いいたします

お世話になります
連続の質問で申し訳ありませんが、紹介いただいた https://pynq.readthedocs.io/en/v2.2.1/pynq_overlays/loading_an_overlay.html内にある
LEDをブリンクするコードbase_overlay.leds[0].toggle()を 下記のコードで確認した結果エラー ('open' is not defined) となります。
ネット経由でjupyter notebookが動作すればこのPythonの問題も発生しないのかもですがエラーの原因で気が付いたことがありましたら教示の程宜しく願います。
またHDMIモニターへのSDのログ表示の件ですが、 ZYBOボード用のxilinuxやlinaro等ではHDMIのドライバーも標準で入っており? SDに焼いた後で起動すればすぐにstartxでgui画面が起動
しますが、Pynqの場合にこのドライバーはネットにあるかご存知でしょうか。 ちなみにPuttyとXmingによるPC上でのgui画面の表示は確認しましたが設定の問題等で動作しませんでした。
多岐に渡る質問で申し訳ありませんがHDMIモニタでgui表示ができないと先に進めませんので宜しく願います。

LED_on_off_9_11.py
from pynq.overlays.base import BaseOverlay
base_overlay = BaseOverlay("base.bit")
base_overlay.leds[0].toggle()

sudo python3.6 LED_on_off_9_11.py
xilinx@MT:~/jupyter_notebooks/base$ sudo python3.6 LED_on_off_9_11.py
Exception ignored in: >
Traceback (most recent call last):
File "/opt/python3.6/lib/python3.6/site-packages/pynq/gpio.py", line 94, in __del__
NameError: name 'open' is not defined

MTさん
todotaniです。

遅くなりましたが、1つ目のHDMI in/outを動かしてみました。
MTさんは、PYNQとTeratermを動かしているPCをどのようにつないでいますか?
1)Ethernetをつないでsshを使ったloginか、2)ひょっとしてUSBポート(J14)を使ったシリアル接続ですか?
どちらでも動くとは思いますが、当方は1)の接続で試しています。

ポイントしたドキュメントのコードに誤りがあるようです。Teratermからipythonを動かして、以下のコードを試して下さい。PYNQのHDMI_INにはNote PCの外部モニタ出力などをつないで、PCのモニター出力をOnにしておきます。

$ sudo ipython

#次のコードを1行入力しては改行を繰り返す
from pynq.overlays.base import BaseOverlay # importのmodule名はこちらが正しい模様
from pynq.lib.video import *

base = BaseOverlay("base.bit")
hdmi_in = base.video.hdmi_in
hdmi_out = base.video.hdmi_out

hdmi_in.configure()
hdmi_in.mode # HDMI_INに入力しているビデオ信号の解像度が表示されます
hdmi_out.configure(hdmi_in.mode)

hdmi_in.start()
hdmi_out.start()

hdmi_in.tie(hdmi_out) # PYNQのHDMI_INに入力した信号がHDMI_OUTにスルー出力されます

WebドキュメントのコードはV2対応のアップデート漏れがあるようですので(よくある話・・)、jupyter notebookを動かして、PYNQの以下のディレクトリにあるサンプルコードを動かしてみるとよいです。
/HOME/jupyter_notebooks/base/video

MTさん
todotaniです

2つ目のご質問の件です。

まず、PYNQのGUIですが、私は、PYNQのX-WINDOWSを動かしたことがないので、このご質問への答えを持ちわせていません。私はいつもsshを使ったCUIか、MacのブラウザからPYNQ_ip_address:9090を開いてjupyter notebookに接続しています。これで、必要な作業はできていますので・・

PYNQにUSBシリアル(J14)経由で接続されているのなら、Teratermでログインしてから、ip aコマンドを実行すると、eth0にDHCPで割り当てられたIPアドレスが分かりますので、PCからそのアドレスに向けてPuttyでssh接続ができないか試してみて下さい。

以下のLEDコードですが、私の環境(ssh接続したコンソールからipythonを使って実行)では、問題なく動きました。あまりお役に立てずすいません。

from pynq.overlays.base import BaseOverlay
base_overlay = BaseOverlay("base.bit")
base_overlay.leds[0].toggle()

お忙しい中 回答ありがとうございます。
1)と2)の質問ですがとりあえず両方ためしてます。接続は外部ルータからのLanコードをpynqのLanコネクタに接続し、pynqはPCからUSBポート(J14)で給電しながらTeratermで
起動ログ確認やコマンド入力をしています。Teraterm上でSSH指定もできますが設定がうまくできていないようです。ifconfigで eth0とeth0:1の2つのIPアドレスが表示されて
おりSD(ubuntu)でssh xilinx@192.168.2.99 (ともう一方の自分のアドレス指定でも) エラーは出てませんでしたがPCのブラウザからはhttp://192.168.2.99:9090/ ではエラーとなります。

marse氏の記事 http://marsee101.blog19.fc2.com/blog-entry-3596.html では自分のアドレスを使用(192.168.2.99ではない方) しておりなぜか疑問です。
 
紹介いただいたxilinxのpynqの資料では2つの接続方法がありもう1つの方法である pynqとPCをLanケーブル 同士で接続しUSBポート(J14)でUSB給電しながらTeratermを使用する方法の場合はhttp://pynq:9090使用とありますが、こちらもNGです。そもそもこの方法ではノートPCにはLanコネクタが1つしかないので外部ルータとの接続はどうするのか、
たぶんWiFiでということだと思いますが。

jupyter notebookがネット経由で起動できない件は他の皆さんの記事ではそういう話はないので私の知識不足が原因ですが、ネット接続が(WiFiを使用するにしても)困難な車中や屋外での作業が多いのでPCに入れたjupyter notebookを使用して進める場合に今後行うBNN等で問題はないでしょうか? 
SD内にjupyter notebooksのホルダーがあったのでいっそSDにjupyter notebookを入れてそこで開発すればssh接続など不要ですっきりすると思うのですが、全然sshで繋が
らない私の愚痴ですが。

HDMI出力についてはpynqのxwindows化が目的でlinuxのコマンド入力が面倒でブラウザからダウンロードしたりマウスでコピペできる環境が欲しいためですがネットで方法を探してみます。またいただいたHDMIのコードは後で確認します。

同じLEDコードがこちらで動作しない件は実行directory等の問題かとも思ったのですが 「gpio.py, line 94, in __del__ NameError: name 'open' is not defined」とあるのでgpio.pyの中を覗いてみましたが力不足でコード解析ができません。PCからそのアドレスに向けてPuttyでssh接続ができないかについてはjupyter notebookが起動できない問題と同じと思いますが後で確認いたします。

MTさん
todotaniです。

基本的なことで、確認済みと思いますが、
PCでコマンドターミナルを開いて、eth0のIPアドレスにpingを行うと応答は返りますか?
ping応答がない場合は、ネットワークに問題があると思います。

例えば、PCのIPアドレス(コマンドプロンプトからipconfigコマンドを実行)が192.168.0.12の場合、PYNQのeth0は192.168.0.xxである必要があります。最初の数字3つ(サブネットID)がPYNQとPC間で一致していないとIP通信はできません。

MTさん
todotaniです。

MTさんのPYNQがうまく動いていない問題で、一つ気になることが出てきました。

> USBポート(J14)でUSB給電しながらTeratermを使用
とありますが、ひょっとしてPCのUSBポートからPYNQに給電していますか?
PCのUSBポートでは、PYNQを動かすために必要な電流を供給できていない可能性があります。J18の外部電源コネクターに「出力2A以上」のACアダプターをつないで給電してみることはできませんか?(その際は、ジャンパーJP5の切り替えも必要です)

お世話になります
pingの確認結果をまずお知らせします。
(1) ネット未接続で自分のPCのIPアドレスに送信 ping xx.xx.xx.xx OK (4回送信OK)
(2) 現在いる場所(自宅でないのでセキュリテイ設定が強固)のルータとLanケーブルでPCと接続し ping 172.168.11.100で OK
(3) (2)でLanケーブルをpynq-z1のLanコネクタに接続しPCとはJ14でUSB給電しながら
 PCからpynqのアドレスに ping 192.168.2.99を送信で NG (たぶんこれがNGなのでブラウザからjupyter notebookに接続できない原因)
自宅ではまだ確認していませんが以前jupyterが起動していなかったので同じと思います。
指摘の「例えば、 必要があります」でIPアドレスの192.168.0.xxで xx以外がeth0でPCのIPアドレスとして認識されていないと通信できないということですが(xxはルータが決める値?) 使用のPCのIPアドレスは169.254.xx.xxで 一方eth0の値は172.168.11.56と上記の(2)の場所での(下2ケタ以外の)値 を表示しています。つまりルータを介して接続する限りルータの場所で変わるためご指摘の同じ値になることはありえないと思うわけですが、上記の結果よりどこがおかしいのか指摘お願いいたします。

USB給電の容量不足の件ですがメーカでは余裕を見た2Aという値でネットでも動作しなかったという話はないのでたぶんこの件はだいじょうぶと思います。

あと前回のLEDの件ですがipythonで実行したら動作しました。 このコードをpythonコードとして実行した場合は 「No module named pynq.overlays.base」エラーがでたので 1行づつ実行する場合の時間間隔の違い以外にもdirectoryやヴァージョンの違いが影響しているのかもですが、前回のエラーが出たgpio.pyの解析も含めていつでもかまいませんのでアドバイス宜しく願います。 

MTさん、
todotaniです。

リプライの内容が理解できず的確なコメントができないのですが、ひょっとして、自宅外から、自宅のLANにつながっているPYNQにpingしようとしていますか?
その場合、自宅ブロードバンドルータ(無線LAN付きルーターなど)のファイヤーウォールをまたいで接続する必要があるため192.168.2.99にpingしても届きません。まずは、PYNQとPCが同じLANセグメントにつながる環境で試して下さい。例えば、PYNQとPC双方がを自宅のルータのHubポートに接続されている状態でpingをやIPアドレスの確認を行って下さい。172.168.11.100は何のIPアドレスですか?

あと、192.168.2.99はPYNQが固有に設定しているプライベートアドレスですので、自宅のブロードバンドルータから付与されているアドレスではありません。このアドレス宛に接続する際は、PYNQのドキュメントにもある通り、PCのIPアドレスをマニュアルで変更して、192.168.2.1とかにする必要があります(つまり、頭3桁の、192.168.2を合わせる必要があるということです)。192.168.2.99には、外部から、ルータをまたいでの接続はできないと思った方がよいです。

LEDの件ですが、PYNQにはpython2.7, 3.5, 3.6の3つのバージョンのpythonが入っています。pythonのライブラリはこのバージョン毎に管理されており、pynq.overlays.base モジュールはpython 3.6のみに入っています。そのため、pythonコードとして実行する際は、
 sudo python3.6 LED_on_off_9_11.py
と起動します。

お世話になります。 機器固有はMACアドレスでした。 失礼しました。

お世話になっています。
昨日の続きで恐縮ですが、pynqをルータにLanコネクタで接続し、同時にPCもLan接続する理由がはっきりしません。特にノートPC使用でLanコネクタが1個しかないので、屋外でも使用したいのでWiFi化を検討しています。
前回も書きましたがjupyter notebookは元からPCに入れているのでこれを使えばいいわけでなぜわざわざサーバー上のを使う必要があるのでしょうか?
PCとpynqはTeratermやPutty+xming等あるいはsambaなどのファイル共有ツールを使用すればコード作成はPCで行いコード転送をこれらのツールで行なった方が快適に作業ができると
思います。Pynqをネット接続する理由はubuntu上でファイルのダウンロードやデータ転送だと思いますが、xwindowの使用の記事がないことからBNNの用途に特化すべきなのかもです。
貴重なブログを私の質問で浪費するのは申し訳ないのでやめますが、ドキュメントのコードに不備もあるようですがそちらでのpynqとPCの具体的接続方法とIPアドレスの指定方法について再度明記いただけましたらありがたいです。宜しく願います。

お世話になります。
https://pynq.readthedocs.io/en/v2.0/getting_started.html を読んで接続は理解できました。
この中でpynqとPCとイーサネットの接続方法の2つのどちらかでもjupyter notebookが起動できるということですね
これによればPCのIPアドレスもSD上のubuntuも全く関係ないですね!!!!
ubuntu本体を内蔵ROMに入れておけばjupyterを使うだけなら全くubuntuやIPアドレスを意識することが不要ですね。
皆さんのネット記事ではまずはSDの起動ログ確認から始まっているのがそもそものの勘違いの元でした。まあ他のzyboボード等では開発にはlinuxが必須ですが,
もしかしてpynqではjupyter notebookだけでBNNが出来るということでしょうか?  将来Polyphony等を使えばHDLも不要でFPGA開発ができてしまうようになるのでは。
ということで無事jupyterが起動すればめでたしだったのですが、上記の資料の2つの方法で起動していません。しばらく試行錯誤したいと思います。

MTさん、
う〜ん、どうにも会話が成立しないようです・・・

MTさんは、PYNQのFPGAを使って、Deep Learningをやりたいとお考えのようですが、そのためにはPYNQの上でLinux(Ubuntu, MTさんがSDと呼ぶもの)を動かして、PYNQ上で動くLinuxをサーバとして、PCなどからリモート接続する必要があるのです。

PYNQでのGUIは、Linux用のディスプレイドライバーが提供されていないため、動きません。多分、Linuxソースをダウンロードして、ドライバーのコードを書き直すことが出来るよな、Linuxカーネルに精通した方でないと無理です(例えばこのリンクで行っているような作業 https://www.slideshare.net/ciniml/pynquipynq)。ですので、PYNQをサーバーとして、sshやwebブラウザーからリモート接続するのです。

・Jupyter notebookはPYNQのLinux(Ubuntu)上で、Linuxが起動した際に自動的にサーバとして起動します
・PCはPYNQでの実行結果を表示するだけです。ですので、PCのJupyter notebookを使うのではなく、PYNQで動いているJupyter(サーバー)にPCのWebブラウザーでリモート接続するのです
・Jupyterはipythonの入出力をWeb UIにしただけで、Jupyterの下では、ipythonが動いています
・さらに、ipythonはpyhon3.6の上に乗っており、pythonコードを一気に動かす代わり、一行毎に実行結果を確認しながら動かすことができるものです
・ですので、おっしゃる通り、jupyterでcodeの動作が確認できたら、テキストエディタでpythonのコードにして、pyhon3.6コマンドで直接実行した方が効率がよいかもしれません
・python3.6で直接動くプログラムを書くのは、仰る通り、PCの高機能エディタを使って行うほうが効率がよいです(PYNQのGUIが使えないため)。ですので、出来上がったプログラムをPYNQにFTPで転送したり、sambaで共有して実行するのはありですが、あくまでコードを実行するのはPYNQのLinux上です。
・なぜならば、PYNQのFPGAにアクセスできるのは、PYNQで動いているLinuxのみだからです。
・PYNQをサーバー、PCをクライアントとするために、PYNQ - PCを同じLANセグメント上でIP接続する必要があります

上記は全て、PYNQで開発を行うための個別事項ではなく、Linuxサーバーで開発を行うための「基本事項」です。上記がご解いただけないようでしたら、このブログで1つ1つの回答を行うことはできませんので、申し訳ありませんが、私の方もこれで終わりにしたいと思います。

ご了承のほどよろしくお願いします。

この記事へのコメントは終了しました。

« Vivado Constraints Wizardによるクロック・入出力制約の作成 | トップページ | PYNQ-Z1のOverlay読み込みとPythonからのFPGA PLの制御(2) »

2023年6月
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30  
無料ブログはココログ