Python から Verilog へ
Polyphony は Python のソースを Verilog へと再解釈(変換)してくれるコンパイラです。
Python の親しみやすさと読みやすさを HDL の世界へ繋げてくれるオープンソースのツールです。
ゆるぼ(緩募)
開発体制もちょっと変わり github の URL も変わりました。
https://github.com/polyphony-dev/polyphony
下記サイトを充実させるべく、ドキュメント作成(将来的にはコンパイラの開発)など手伝ってくれる人(ボランティアです、、、)ちょっと募集してます。
https://polyphony.tech
何が出来るの?
- RISC-V
- ラズパイカメラ
- データセンター
- Vivado へ埋め込み
なんちゃって RISC-V
Polyphony を使うと RISC-V も簡単に作る事が出来ます(近日公開予定)。周辺の I/F が充実していないので今一つ実用性に乏しいですが、CPU を作る事が簡単にできます。
一応、4年前に発表してます。
https://www.ieice.org/ken/paper/20170926TbX1/
VM みたいなものは簡単にできます。Retro という FORTH 系の言語も動いています。
http://polyphony.tech/blog/19/07300.html
ラズパイカメラへの接続
Zynq は CPU もついていてすごく便利ですね。でも、例えばラズパイカメラなんかをつないだ時に I2C の初期設定をソフト側でしないとカメラとか動きませんね。
ソフトの設定が入ると FPGA 以外の事を要求され、簡単にテストしたくても難しくなってしまいます。そんなときに Polyphony !!
I2C のシーケンスと GPIO のシーケンスを書いておけばソフトの助けなしにいきなり周辺機器を動作させることが出来ます。
INIT_DATA_MODE1 = [
0x0100, 0x00,
0x30eb, 0x05,
0x30eb, 0x0c,
...中略...
]
で Python のソース(抜粋)
from imx219_init_data import INIT_DATA_MODE1, INIT_DATA_MODE7
IMX219_ADDR=0x10
@module
class imx219_go:
def __init__(self):
self.i2c = i2c_master()
で出来たソース
module imx219_go_m
(
input wire clk,
input wire rst,
output reg done,
output reg cam_gpio,
output reg cam_clk,
input wire kick_in,
input wire re_flush_in,
input wire debug_print_q_full,
input wire debug_print_q_will_full,
output reg signed [7:0] debug_print_q_din,
output reg debug_print_q_write,
output reg i2c_scl_o,
output reg i2c_scl_t,
output reg i2c_sda_o,
output reg i2c_sda_t,
input wire i2c_sda_i,
input wire i2c_scl_i
);
データセンター
U50 をつかって実験してます。U50 で AXI-Stream + RTL(Verilog-HDL) でデータ通信が出来ることがわかりました。
名称をそろえておけば v++ がよしなにリンクしてくれるみたいです。であれば、Polyphony で出来るはず!
@module
class AXIS:
def __init__(self, interval):
self.video_in_TDATA = Port(bit8, 'in')
self.video_in_TVALID = Port(bit, 'in')
self.video_in_TREADY = Port(bit, 'out')
self.video_in_TUSER = Port(bit, 'in')
self.video_in_TLAST = Port(bit, 'in')
self.video_out_TDATA = Port(bit8, 'out')
self.video_out_TVALID = Port(bit, 'out')
self.video_out_TREADY = Port(bit, 'in')
self.video_out_TUSER = Port(bit, 'out')
self.video_out_TLAST = Port(bit, 'out')
self.interval = interval
self.append_worker(self.main)
コンパイルだ!
module AXIS_axis
(
input wire clk,
input wire rst,
input wire [7:0] video_in_TDATA,
input wire video_in_TVALID,
output reg video_in_TREADY = 0,
input wire video_in_TUSER,
input wire video_in_TLAST,
output reg [7:0] video_out_TDATA = 0,
output reg video_out_TVALID = 0,
input wire video_out_TREADY,
output reg video_out_TUSER = 0,
output reg video_out_TLAST = 0
);
できるじゃん!!Polyphony おそるべし。(clk と rst がちょっと名称が違うのでそこは修正の必要あり。そして Polyphony の今後の課題)
Vivado 対応
Vivado への対応をちょっとやってみました。通常は生成された Verilog-HDL を Vivado に張り付けるだけなので、特段、Polyphony 対応というほどでもありません。ただ、それだと Python のソースを修正したら、毎回、Verilog-HDL も直さないといけません。不便ですね。
Xilinx の IPXACT を見よう見まねで Polyphony にフィットするように書いてみました。
アイコンが Vivado HLS のままで気持ち悪いですが、中身は Python です。ダブルクリックしてみます。
ちゃんとパラメタを受け付けてます。ソースは Python 。Config.Interval で値を設定できます(もちろん自動生成なので使用者は Python ということは意識しません)。
from polyphony import testbench, module, is_worker_running
from polyphony.io import Port
from polyphony.typing import bit
from configs import Config
@module
class Blink:
def __init__(self, interval):
self.led = Port(bit, 'out')
self.interval = interval
self.append_worker(self.main)
def main(self):
led:bit = 1
while is_worker_running():
self.led(led)
led = ~led
self._wait()
def _wait(self):
for i in range(self.interval // 2):
pass
blink = Blink(Config.INTERVAL)
Polyphony(2022年版) の今後
現在、次期バージョン(timed) を絶賛開発中です。
これができると、細かい、プロトコルを Python で書いて、さらにそれを Python でラッピングして、main の処理やっぱり Python で書く!ということができます。
今後も Polyphony をよろしくね。