...
 
Commits (5)
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*.out *.out
sim sim
solver solver
!/solver
# Python files # Python files
*.pyc *.pyc
......
...@@ -17,18 +17,22 @@ from urllib.parse import urlparse ...@@ -17,18 +17,22 @@ from urllib.parse import urlparse
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../../solver') sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../../solver')
import BoardStr import BoardStr
import adc2018solver as pynqrouter
import Solver2017
import Solver2018
import Solver2018Ultra
app = Flask(__name__) app = Flask(__name__)
args = {} args = {}
client_baseurl = "" client_baseurl = ""
pynqrouter = None
@app.route('/start', methods=["POST"]) @app.route('/start', methods=["POST"])
def start(): def start():
# global pynq_thread
global args global args
global client_baseurl global client_baseurl
global pynqrouter
ans = {"status": "None", "answer": "", "client": client_baseurl} ans = {"status": "None", "answer": "", "client": client_baseurl}
...@@ -48,6 +52,7 @@ def start(): ...@@ -48,6 +52,7 @@ def start():
"name": qname, "name": qname,
"host": args['host'], "host": args['host'],
"client": client_baseurl, "client": client_baseurl,
"problem": qstr,
"req_id": request.form['req_id'], "req_id": request.form['req_id'],
"resolver": request.form['resolver'] "resolver": request.form['resolver']
} }
...@@ -70,6 +75,8 @@ def start(): ...@@ -70,6 +75,8 @@ def start():
@app.route('/stop') @app.route('/stop')
def stop(): def stop():
global pynqrouter
if pynqrouter.solver_thread is None: if pynqrouter.solver_thread is None:
ans = {"status": "No threads"} ans = {"status": "No threads"}
else: else:
...@@ -82,6 +89,8 @@ def stop(): ...@@ -82,6 +89,8 @@ def stop():
@app.route("/status") @app.route("/status")
def status(): def status():
global pynqrouter
res_mes = "" res_mes = ""
if pynqrouter.solver_thread is None: if pynqrouter.solver_thread is None:
...@@ -113,11 +122,23 @@ if __name__ == "__main__": ...@@ -113,11 +122,23 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser(description="PYNQ client.") parser = argparse.ArgumentParser(description="PYNQ client.")
parser.add_argument("-p", "--port", action="store", type=int, default=5000, help="Port") parser.add_argument("-p", "--port", action="store", type=int, default=5000, help="Port")
parser.add_argument("-H", "--host", action="store", type=str, default="192.168.4.1:5000", help="Host address") parser.add_argument("-H", "--host", action="store", type=str, default="192.168.5.1:5000", help="Host address")
parser.add_argument("-s", "--solver", action="store", type=str, default="2017", help="2017, 2018, 2018Ultra, 2018Ishi")
parser.add_argument("--debug", action="store_true", default=False, help="Debug mode.") parser.add_argument("--debug", action="store_true", default=False, help="Debug mode.")
parser.add_argument("-v", "--verbose", action="store_true", default=False, help="Verbose.") parser.add_argument("-v", "--verbose", action="store_true", default=False, help="Verbose.")
args = vars(parser.parse_args()) args = vars(parser.parse_args())
if args['solver'] == '2017':
pynqrouter = Solver2017
elif args['solver'] == '2018':
pynqrouter = Solver2018
elif args['solver'] == '2018Ultra':
pynqrouter = Solver2018Ultra
elif args['solver'] == '2018Ishi':
raise NotImplementedError()
else:
pynqrouter = Solver2017
if args["debug"]: if args["debug"]:
app.debug = True app.debug = True
app.run(host='0.0.0.0', port=args["port"], threaded=True) app.run(host='0.0.0.0', port=args["port"], threaded=True)
......
...@@ -81,6 +81,7 @@ def solve(boardstr, seed=12345, zero_padding=False, option=dict()): ...@@ -81,6 +81,7 @@ def solve(boardstr, seed=12345, zero_padding=False, option=dict()):
res = { res = {
'client': option['client'], 'client': option['client'],
'qname': option['name'], 'qname': option['name'],
'problem': option['problem'],
'solution': '', 'solution': '',
'cputime': -1.0, 'cputime': -1.0,
'req_id': option['req_id'], 'req_id': option['req_id'],
...@@ -114,10 +115,17 @@ def solve(boardstr, seed=12345, zero_padding=False, option=dict()): ...@@ -114,10 +115,17 @@ def solve(boardstr, seed=12345, zero_padding=False, option=dict()):
print('Overlay loaded!') print('Overlay loaded!')
# MMIO 接続 (pynqrouter) # MMIO 接続 (pynqrouter)
mmio = MMIO(int(PL.ip_dict[IP][0], 16), int(PL.ip_dict[IP][1], 16)) if isinstance(PL.ip_dict[IP][0], int):
mmio = MMIO(PL.ip_dict[IP][0], PL.ip_dict[IP][1])
else:
mmio = MMIO(int(PL.ip_dict[IP][0], 16), int(PL.ip_dict[IP][1], 16))
# MMIO 接続 & リセット (LED) # MMIO 接続 & リセット (LED)
mmio_led = MMIO(int(PL.ip_dict[IP_LED][0], 16), int(PL.ip_dict[IP_LED][1], 16)) if isinstance(PL.ip_dict[IP_LED][0], int):
mmio_led = MMIO(PL.ip_dict[IP_LED][0], PL.ip_dict[IP_LED][1])
else:
mmio_led = MMIO(int(PL.ip_dict[IP_LED][0], 16), int(PL.ip_dict[IP_LED][1], 16))
mmio_led.write(0, 0) mmio_led.write(0, 0)
# 入力データをセット # 入力データをセット
...@@ -201,6 +209,7 @@ def solve(boardstr, seed=12345, zero_padding=False, option=dict()): ...@@ -201,6 +209,7 @@ def solve(boardstr, seed=12345, zero_padding=False, option=dict()):
res = { res = {
'client': option['client'], 'client': option['client'],
'qname': option['name'], 'qname': option['name'],
'problem': option['problem'],
'solution': solution, 'solution': solution,
'cputime': elapsed, 'cputime': elapsed,
'req_id': option['req_id'], 'req_id': option['req_id'],
......
#!/opt/python3.6/bin/python3.6
# -*- coding: utf-8 -*-
"""
PYNQ 上で pynqrouter を実行する。
"""
from pynq import Overlay
from pynq import PL
from pynq import MMIO
import argparse
import requests
import sys
import time
import threading
import BoardStr
# Settings -- pynqrouter
OFFSET_BOARD_LOW = 0x10000 # 0x10000 ~ 0x1ffff
OFFSET_BOARD_HIGH = 0x20000 # 0x20000 ~ 0x2ffff
OFFSET_SEED = 0x30000 # 0x30000
OFFSET_STATUS = 0x30008 # 0x30008
MAX_X = 72
MAX_Y = 72
MAX_Z = 8
BITWIDTH_Z = 3
BOARD_WORDS = (MAX_X * MAX_Y * MAX_Z) // 4
# Settings -- LED
IP_LED = 'SEG_axi_gpio_0_Reg'
BS_IP = [
('router_design.bit', 'SEG_pynqrouter_0_Reg')
]
solver_thread = None
class StoppableThread(threading.Thread):
def __init__(self, target, args=()):
super(StoppableThread, self).__init__(target=target, args=args)
self._status = 'running'
def stop(self):
if self._status == 'running':
self._status = 'stopping'
def stopped(self):
self._status = 'stopped'
def is_running(self):
return (self._status == 'running')
def is_stopping(self):
return (self._status == 'stopping')
def is_stopped(self):
return (self._status == 'stopped')
def start_solver(boardstr, seed, option):
global solver_thread
if solver_thread is None:
solver_thread = StoppableThread(target=solve, args=(boardstr, int(seed), False, option))
solver_thread.start()
def stop_solver():
global solver_thread
if solver_thread is not None:
if solver_thread.is_running():
solver_thread.stop()
solver_thread.join()
solver_thread = None
def solve(boardstr, seed=12345, zero_padding=False, option=dict()):
global solver_thread
print('boardstr:')
print(boardstr)
print('seed:')
print(seed)
print('')
res = {
'client': option['client'],
'qname': option['name'],
'problem': option['problem'],
'solution': '',
'cputime': -1.0,
'req_id': option['req_id'],
'solved': False
}
# LINE数を数えてコンフィグするbitstreamを分岐
line_num = boardstr.count('L')
if line_num < 1023:
BITSTREAM = BS_IP[0][0]
IP = BS_IP[0][1]
else:
solver_thread.stopped()
solver_thread = None
if "host" in option:
r = requests.post("http://{}/post".format(option['host']), data=res)
return res
# ボード文字列から X, Y, Z を読んでくる
size_x = (ord(boardstr[1]) - ord('0')) * 10 + (ord(boardstr[2]) - ord('0'))
size_y = (ord(boardstr[4]) - ord('0')) * 10 + (ord(boardstr[5]) - ord('0'))
size_z = (ord(boardstr[7]) - ord('0'))
# Overlay 読み込み
OL = Overlay(BITSTREAM)
OL.download()
print(OL.ip_dict)
print('Overlay loaded!')
# MMIO 接続 (pynqrouter)
if isinstance(PL.ip_dict[IP][0], int):
mmio = MMIO(PL.ip_dict[IP][0], PL.ip_dict[IP][1])
else:
mmio = MMIO(int(PL.ip_dict[IP][0], 16), int(PL.ip_dict[IP][1], 16))
# MMIO 接続 & リセット (LED)
if isinstance(PL.ip_dict[IP_LED][0], int):
mmio_led = MMIO(PL.ip_dict[IP_LED][0], PL.ip_dict[IP_LED][1])
else:
mmio_led = MMIO(int(PL.ip_dict[IP_LED][0], 16), int(PL.ip_dict[IP_LED][1], 16))
mmio_led.write(0, 0)
# 入力データをセット
imem = pack(boardstr)
for i in range(len(imem)):
mmio.write(OFFSET_BOARD_LOW + (i * 4), imem[i])
mmio.write(OFFSET_SEED, seed)
# スタート
# ap_start (0 番地の 1 ビット目 = 1)
mmio.write(0, 1)
print('Start!')
time_start = time.time()
# ap_done (0 番地の 2 ビット目 = 2) が立つまで待ってもいいが
# done は一瞬だけ立つだけのことがあるから
# ap_idle (0 番地の 3 ビット目 = 4) を待ったほうが良い
iteration = 0
while (mmio.read(0) & 4) == 0:
# 動いてるっぽく見えるようにLチカさせる
iteration += 1
if iteration == 10000:
mmio_led.write(0, 3)
elif 20000 <= iteration:
mmio_led.write(0, 12)
iteration = 0
if (solver_thread is not None) and (not solver_thread.is_running()):
solver_thread.stopped()
solver_thread = None
if "host" in option:
r = requests.post("http://{}/post".format(option['host']), data=res)
return res
# 完了の確認
print('Done!')
print('control:', mmio.read(0))
time_done = time.time()
elapsed = time_done - time_start
print('elapsed:', elapsed)
print('')
# 状態の取得
status = int(mmio.read(OFFSET_STATUS))
print('status:', status)
if status != 0:
# 解けなかったらLEDを消す
mmio_led.write(0, 0)
sys.stderr.write('Cannot solve it!\n')
if "host" in option:
r = requests.post("http://{}/post".format(option['host']), data=res)
solver_thread = None
return res
print('Solved!')
# 解けたらLEDを全部つける
mmio_led.write(0, 15)
# 出力
omem = []
for i in range(BOARD_WORDS):
omem.append(mmio.read(OFFSET_BOARD_LOW + (i * 4)))
boards_low = unpack(omem)
omem = []
for i in range(BOARD_WORDS):
omem.append(mmio.read(OFFSET_BOARD_HIGH + (i * 4)))
boards_high = unpack(omem)
boards = []
for _high, _low in zip(boards_high, boards_low):
boards.append(_high * 256 + _low)
# 回答の生成
solution = ('SIZE ' + str(size_x) + 'X' + str(size_y) + 'X' + str(size_z) + '\n')
for z in range(size_z):
solution += ('LAYER ' + str(z + 1) + '\n')
for y in range(size_y):
for x in range(size_x):
if x != 0:
solution += ','
i = ((x * MAX_X + y) << BITWIDTH_Z) | z
if zero_padding:
solution += '{0:0>2}'.format(boards[i]) # 2桁の0詰め
else:
solution += str(boards[i]) # 普通に表示
solution += '\n'
res = {
'client': option['client'],
'qname': option['name'],
'problem': option['problem'],
'solution': solution,
'cputime': elapsed,
'req_id': option['req_id'],
'solved': True
}
if "resolver" in option:
r = requests.post("http://{}/post".format(option['resolver']), data=res)
elif "host" in option:
r = requests.post("http://{}/post".format(option['host']), data=res)
if solver_thread is not None:
solver_thread.stopped()
solver_thread = None
return res
def main():
parser = argparse.ArgumentParser(description="Solver with pynqrouter")
# 入出力
parser.add_argument('-i', '--input', action='store', nargs='?', default=None, type=str,
help='Path to input problem file')
parser.add_argument('-b', '--boardstr', action='store', nargs='?', default=None, type=str,
help='Problem boardstr (if you want to solve directly)')
parser.add_argument('-o', '--output', action='store', nargs='?', default=None, type=str,
help='Path to output answer file')
# ソルバオプション
parser.add_argument('-t', '--terminals', action='store', nargs='?', default='initial', type=str,
help='Terminals order (initial, edgefirst, or random) (default: initial)')
parser.add_argument('-s', '--seed', action='store', nargs='?', default=12345, type=int,
help='Random seed')
# 出力オプション
parser.add_argument('-p', '--print', action='store_true', default=False,
help='Enable to print the solution')
parser.add_argument('-z', '--zero-padding', action='store_true', default=False,
help='Enable to do zero-padding')
args = parser.parse_args()
if args.input is not None:
# 問題ファイルの読み込み
with open(args.input, 'r') as f:
lines = f.readlines()
# 問題ファイルを boardstr に変換
boardstr = BoardStr.conv_boardstr(lines, args.terminals, args.seed)
elif args.boardstr is not None:
boardstr = args.boardstr
else:
sys.stderr.write('Specify at least "input" or "boardstr"!\n')
sys.exit(1)
result = solve(boardstr, args.seed)
if result['solved'] == False:
sys.exit(1)
# 表示 & ファイル出力
if args.print:
print('')
print('SOLUTION')
print('========')
print(result['solution'])
if args.output is not None:
with open(args.output, 'w') as f:
f.write(result['solution'])
def pack(_str):
"""
ボードストリング文字列をMMIOメモリにパックする
"""
_mem = [ 0 for _ in range(MAX_X * MAX_Y * MAX_Z // 4) ]
for i in range(len(_str)):
_index = i // 4;
_offset = i % 4;
if _offset == 0:
_mem[_index] = _mem[_index] | (ord(_str[i]))
elif _offset == 1:
_mem[_index] = _mem[_index] | (ord(_str[i]) << 8)
elif _offset == 2:
_mem[_index] = _mem[_index] | (ord(_str[i]) << 16)
elif _offset == 3:
_mem[_index] = _mem[_index] | (ord(_str[i]) << 24)
return _mem
def unpack(_mem):
"""
MMIOメモリからボード情報をアンパックする
"""
_boards = [ 0 for _ in range(MAX_X * MAX_Y * MAX_Z) ]
for i in range(len(_mem)):
_boards[4 * i ] = (_mem[i]) & 255
_boards[4 * i + 1] = (_mem[i] >> 8) & 255
_boards[4 * i + 2] = (_mem[i] >> 16) & 255
_boards[4 * i + 3] = (_mem[i] >> 24) & 255
return _boards
if __name__ == '__main__':
main()
This diff is collapsed.