スィングしなけれりゃ意味がない(It Don't Mean A Thing. If It Ain't Got That Swing)。最近ではめっきり聞かなくなったが、エラの歌はいつもスィングしている。いつまでもエラの時代じゃない。次の次の次の時代はエスペランザみたいな人が道なき道を作っていく。
そうしないと意味がないとまでは言わないが、FPGA で物を作るならパイプラインは必須だ。Polyphony でもついにパイプラインの機能が取り入れられた。まだ、準備段階にある機能だが github の devel から clone すれば、その機能を試すことが出来る。
ソースの例を示そう。
pipeline
@rule(scheduling='pipeline')
def proc(self):
a0:uint18 = 0
a1:uint18 = 0
...
後略
...
実に単純だ。@rule というデコレータをつけるだけである。引数として設定されている scheduling='pipeline' でパイプライン化の指示をしていることになる。
これで数日に渡ったフィルタ・プログラムの完成である。全体像は次のようになる。
デザイナーはフィルター部分を独自に作れば様々な対応ができるだろう。参考までに UART と SPI を統合したフィルターのソースをつける。
filter.py
from polyphony import rule
import polyphony
from polyphony import is_worker_running
from polyphony.io import Port, Queue
from polyphony.typing import bit, int8, int16, int18
from polyphony.timing import clksleep, clkfence, wait_rising, wait_falling
@polyphony.module
class Filter:
def __init__(self):
self.uart = uart.Transmitter()
self.spi_in = AD7091R_SPIC()
self.q = Queue(int16, 'any', maxsize=10)
self.append_worker(self.read_proc)
self.append_worker(self.proc)
def read_proc(self):
while is_worker_running():
#wait_rising(self.spi_in.data_ready)
data = self.spi_in.dout.rd()
self.q.wr(data)
@rule(scheduling='pipeline')
def proc(self):
a0:int18 = 0
a1:int18 = 0
a2:int18 = 0
a3:int18 = 0
while is_worker_running():
data:int16 = self.q.rd()
a0 = a1 + data
a1 = a2 + data
a2 = a3 + data
a3 = data
#print(data)
self.uart.write_hex16(data)
@polyphony.testbench
def test(m):
datas = (0xdead, 0xbeef, 0xffff, 0x0000, 0x800)
for data in datas:
m.din.wr(data)
for i in range(5):
print(m.q.rd())
clksleep(10)
if __name__ == '__main__':
filter = Filter()
test(filter)