Moved to more fusesoc like build style

Signed-off-by: Joppe Blondel <joppe@blondel.nl>
This commit is contained in:
2022-09-05 12:23:55 +02:00
parent 7eecf25894
commit 7aa7fd59b0
13 changed files with 333 additions and 306 deletions

View File

@ -1,26 +1,30 @@
[project] [project]
name = spartan6_project name = spartan6_project
version = 0.1 version = 0.1
out_dir = OUT out_dir = OUT
build_dir = BUILD build_dir = BUILD
[server] [server]
hostname = localhost hostname = localhost
port = 2020 port = 2020
privkey = /home/joppe/.ssh/id_rsa privkey = /home/joppe/.ssh/id_rsa
pubkey = /home/joppe/.ssh/id_rsa.pub pubkey = /home/joppe/.ssh/id_rsa.pub
[target:default] [target.synth]
family = spartan6 toolchain = ISE
device = xc6slx9
package = tqg144
speedgrade = -2
toolchain = ISE
[build:default] # Toolchain settings
target = default family = spartan6
toplevel = toplevel device = xc6slx9
constraints = CON/toplevel.ucf package = tqg144
src_vhdl = RTL/toplevel.vhd speedgrade = -2
src_verilog = toplevel = toplevel
src_sysverilog = #xst_opts =
#ngdbuild_opts =
#map_opts =
#par_opts =
# Fileset
files_vhdl = RTL/toplevel.vhd
#files_verilog =
files_con = CON/toplevel.ucf

View File

@ -1,126 +0,0 @@
from asyncio import constants
import threading
import shutil
import os
import time
import subprocess
import signal
import random
def needed_files(config, target) -> list:
if not config.has_section(f'build:{target}'):
print("ERROR: config file has no build section for target")
return None
outdir = f"{config.get('project', 'out_dir', fallback='out')}"
needed_files = [
f'{outdir}/{target}/synth.ngc',
]
for s in config.get(f'build:{target}', 'constraints', fallback="").split():
needed_files.append(s)
return needed_files
def generated_files(config, target) -> list:
outdir = f"{config.get('project', 'out_dir', fallback='out')}"
return [
f'{outdir}/{target}/impl-ngd.log',
f'{outdir}/{target}/impl-map.log',
f'{outdir}/{target}/impl-par.log',
f'{outdir}/{target}/netgen.log',
f'{outdir}/{target}/{target}.v',
f'{outdir}/{target}/{target}.sdf',
f'{outdir}/{target}/impl.ncd',
f'{outdir}/{target}/impl.pcf',
]
def do(config, target, log, subprocesses, prefix='.') -> int:
log("Implement:")
if not config.has_section(f'build:{target}'):
log("ERROR: config file has no build section for target")
return 1
devtarget = f'target:{config.get(f"build:{target}", "target", fallback="")}'
if not config.has_section(devtarget):
log("ERROR: config file has no section for device target")
return 1
device = f"{config.get(devtarget, 'device', fallback='')}{config.get(devtarget, 'speedgrade', fallback='')}-{config.get(devtarget, 'package', fallback='')}"
builddir = f"{prefix}/{config.get('project', 'build_dir', fallback='.build')}"
outdir = f"{prefix}/{config.get('project', 'out_dir', fallback='out')}"
os.makedirs(builddir, exist_ok=True)
curdir = f"{os.getcwd()}/{prefix}"
contstraints = []
for s in config.get(f'build:{target}', 'constraints', fallback="").split():
contstraints.append(f"{curdir}/{s}")
log(" - Executing ngdbuild")
p = subprocess.Popen(f"ngdbuild -intstyle xflow -p {device} -uc {contstraints[0]} {curdir}/{outdir}/{target}/synth.ngc impl.ngd", shell=True, cwd=builddir, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocesses.append(p)
while p.poll() is None:
time.sleep(1)
res = p.returncode
if res:
log(" - ERROR: return code is", res)
log(" - copy log")
os.makedirs(f'{outdir}/{target}', exist_ok=True)
shutil.copy(f'{builddir}/impl.bld', f'{outdir}/{target}/impl-ngd.log')
return res
log(" - Executing map")
p = subprocess.Popen(f"map -intstyle xflow -p {device} -detail -ol high -xe n -w impl.ngd -o impl.map.ncd impl.pcf", shell=True, cwd=builddir, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocesses.append(p)
while p.poll() is None:
time.sleep(1)
res = p.returncode
if res:
log(" - ERROR: return code is", res)
log(" - copy log")
os.makedirs(f'{outdir}/{target}', exist_ok=True)
shutil.copy(f'{builddir}/impl.bld', f'{outdir}/{target}/impl-ngd.log')
shutil.copy(f'{builddir}/impl.map.mrp', f'{outdir}/{target}/impl-map.log')
return res
log(" - Executing par")
p = subprocess.Popen(f"par -intstyle xflow -ol high -xe n -w impl.map.ncd impl.pcf | tee impl.par.log", shell=True, cwd=builddir, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocesses.append(p)
while p.poll() is None:
time.sleep(1)
res = p.returncode
if res:
log(" - ERROR: return code is", res)
log(" - copy log")
os.makedirs(f'{outdir}/{target}', exist_ok=True)
shutil.copy(f'{builddir}/impl.bld', f'{outdir}/{target}/impl-ngd.log')
shutil.copy(f'{builddir}/impl.map.mrp', f'{outdir}/{target}/impl-map.log')
shutil.copy(f'{builddir}/impl.par.log', f'{outdir}/{target}/impl-par.log')
return res
log(" - Executing netgen")
p = subprocess.Popen(f"netgen -intstyle xflow -sim -ofmt verilog -w -insert_glbl true -sdf_anno true -ism impl.map.ncd > netgen.log", shell=True, cwd=builddir, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocesses.append(p)
while p.poll() is None:
time.sleep(1)
res = p.returncode
if res:
log(" - ERROR: return code is", res)
log(" - copy log")
os.makedirs(f'{outdir}/{target}', exist_ok=True)
shutil.copy(f'{builddir}/impl.bld', f'{outdir}/{target}/impl-ngd.log')
shutil.copy(f'{builddir}/impl.map.mrp', f'{outdir}/{target}/impl-map.log')
shutil.copy(f'{builddir}/impl.par.log', f'{outdir}/{target}/impl-par.log')
shutil.copy(f'{builddir}/netgen.log', f'{outdir}/{target}/netgen.log')
return res
log(" - copy output files")
os.makedirs(f'{outdir}/{target}', exist_ok=True)
shutil.copy(f'{builddir}/impl.bld', f'{outdir}/{target}/impl-ngd.log')
shutil.copy(f'{builddir}/impl.map.mrp', f'{outdir}/{target}/impl-map.log')
shutil.copy(f'{builddir}/impl.par.log', f'{outdir}/{target}/impl-par.log')
shutil.copy(f'{builddir}/impl.pcf', f'{outdir}/{target}/impl.pcf')
shutil.copy(f'{builddir}/impl.pcf.ncd', f'{outdir}/{target}/impl.ncd')
shutil.copy(f'{builddir}/impl.map.v', f'{outdir}/{target}/{target}.v')
shutil.copy(f'{builddir}/impl.map.sdf', f'{outdir}/{target}/{target}.sdf')
shutil.copy(f'{builddir}/netgen.log', f'{outdir}/{target}/netgen.log')
return 0

View File

@ -1,80 +0,0 @@
import threading
import shutil
import os
import time
import subprocess
import signal
import random
def needed_files(config, target) -> list:
if not config.has_section(f'build:{target}'):
print("ERROR: config file has no build section for target")
return None
needed_files = []
for s in config.get(f'build:{target}', 'src_vhdl', fallback="").split():
needed_files.append(s)
for s in config.get(f'build:{target}', 'src_verilog', fallback="").split():
needed_files.append(s)
for s in config.get(f'build:{target}', 'src_sysverilog', fallback="").split():
needed_files.append(s)
return needed_files
def generated_files(config, target) -> list:
outdir = f"{config.get('project', 'out_dir', fallback='out')}"
return [
f'{outdir}/{target}/synth.log',
f'{outdir}/{target}/synth.ngc',
]
def do(config, target, log, subprocesses, prefix='.') -> int:
log("Synthesize:")
if not config.has_section(f'build:{target}'):
log("ERROR: config file has no build section for target")
return 1
devtarget = f'target:{config.get(f"build:{target}", "target", fallback="")}'
if not config.has_section(devtarget):
log("ERROR: config file has no section for device target")
return 1
device = f"{config.get(devtarget, 'device', fallback='')}{config.get(devtarget, 'speedgrade', fallback='')}-{config.get(devtarget, 'package', fallback='')}"
builddir = f"{prefix}/{config.get('project', 'build_dir', fallback='.build')}"
outdir = f"{prefix}/{config.get('project', 'out_dir', fallback='out')}"
os.makedirs(builddir, exist_ok=True)
curdir = f"{os.getcwd()}/{prefix}"
log(" - writing project file")
with open(f'{builddir}/syn.prj', 'w') as f:
for s in config.get(f'build:{target}', 'src_vhdl', fallback="").split():
f.write(f"vhdl work {curdir}/{s}\n")
for s in config.get(f'build:{target}', 'src_verilog', fallback="").split():
f.write(f"verilog work {curdir}/{s}\n")
for s in config.get(f'build:{target}', 'src_sysverilog', fallback="").split():
f.write(f"verilog work {curdir}/{s}\n")
log(" - writing project generation file")
with open(f'{builddir}/prj.scr', 'w') as f:
f.write(f'run\n-ifn syn.prj\n-ofn syn.ngc\n-ifmt mixed\n')
f.write(f'-top {config.get(f"sources:{target}", "toplevel", fallback="toplevel")}\n')
f.write(f'-p {device}\n-glob_opt max_delay -opt_mode speed')
log(" - Executing xst")
p = subprocess.Popen("xst -intstyle xflow -ifn prj.scr", shell=True, cwd=builddir, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocesses.append(p)
while p.poll() is None:
time.sleep(1)
res = p.returncode
if res:
log(" - ERROR: return code is", res)
log(" - copy log")
os.makedirs(f'{outdir}/{target}', exist_ok=True)
shutil.copy(f'{builddir}/prj.srp', f'{outdir}/{target}/synth.log')
return res
log(" - copy output files")
os.makedirs(f'{outdir}/{target}', exist_ok=True)
shutil.copy(f'{builddir}/syn.ngc', f'{outdir}/{target}/synth.ngc')
shutil.copy(f'{builddir}/prj.srp', f'{outdir}/{target}/synth.log')
return 0

View File

@ -0,0 +1,35 @@
from .util_ISE.xst import xst
from .util_ISE.ngdbuild import ngdbuild
from .util_ISE.map import map
from .util_ISE.par import par
from .util_ISE.netgen import netgen
def do(config, target, log, subprocesses, prefix='.'):
log("Syntesize:")
res = xst(config, target, log, subprocesses, prefix)
if res != 0:
print("ERROR: xst returned with", res)
return res
log("Implement")
res = ngdbuild(config, target, log, subprocesses, prefix)
if res != 0:
print("ERROR: ngdbuild returned with", res)
return res
res = map(config, target, log, subprocesses, prefix)
if res != 0:
print("ERROR: map returned with", res)
return res
res = par(config, target, log, subprocesses, prefix)
if res != 0:
print("ERROR: par returned with", res)
return res
res = netgen(config, target, log, subprocesses, prefix)
if res != 0:
print("ERROR: netgen returned with", res)
return res

View File

@ -0,0 +1,36 @@
import shutil
import os
import time
import subprocess
def map(config, target, log, subprocesses, prefix='.') -> int:
log(" - parsing options")
device = config.get(f'target.{target}', 'device', fallback='')
package = config.get(f'target.{target}', 'package', fallback='')
speedgrade = config.get(f'target.{target}', 'speedgrade', fallback='')
map_opts = config.get(f'target.{target}', 'map_opts', fallback='')
build_dir = config.get(f'project', 'build_dir', fallback='build')
out_dir = config.get(f'project', 'out_dir', fallback='out')
devstring = f'{device}{speedgrade}-{package}'
prefix = f'{os.getcwd()}/{prefix}'
build_dir = f'{prefix}/{build_dir}'
out_dir = f'{prefix}/{out_dir}/{target}'
log(" - creating output directories")
os.makedirs(build_dir, exist_ok=True)
os.makedirs(out_dir, exist_ok=True)
log(" - run map")
p = subprocess.Popen(f"map -intstyle xflow -p {devstring} -detail {map_opts} -ol high -xe n -w {out_dir}/{target}.ngd -o impl.map.ncd impl.pcf",
shell=True, cwd=build_dir,
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocesses.append(p)
while p.poll() is None:
time.sleep(1)
res = p.returncode
log(" - copy logs")
shutil.copy(f'{build_dir}/impl.map.mrp', f'{out_dir}/map.log')
return res

View File

@ -0,0 +1,37 @@
import shutil
import os
import time
import subprocess
def netgen(config, target, log, subprocesses, prefix='.') -> int:
log(" - parsing options")
netgen_opts = config.get(f'target.{target}', 'netgen_opts', fallback='')
build_dir = config.get(f'project', 'build_dir', fallback='build')
out_dir = config.get(f'project', 'out_dir', fallback='out')
prefix = f'{os.getcwd()}/{prefix}'
build_dir = f'{prefix}/{build_dir}'
out_dir = f'{prefix}/{out_dir}/{target}'
log(" - creating output directories")
os.makedirs(build_dir, exist_ok=True)
os.makedirs(out_dir, exist_ok=True)
log(" - run netgen")
p = subprocess.Popen(f"netgen -intstyle xflow -sim -ofmt verilog -w -insert_glbl true -sdf_anno true {netgen_opts} -ism {out_dir}/{target}.ncd > netgen.log",
shell=True, cwd=build_dir,
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocesses.append(p)
while p.poll() is None:
time.sleep(1)
res = p.returncode
log(" - copy logs")
shutil.copy(f'{build_dir}/netgen.log', f'{out_dir}/netgen.log')
if res==0:
log(" - copy output files")
shutil.copy(f'{build_dir}/{target}.v', f'{out_dir}/{target}.v')
shutil.copy(f'{build_dir}/{target}.sdf', f'{out_dir}/{target}.sdf')
return res

View File

@ -0,0 +1,41 @@
import shutil
import os
import time
import subprocess
def ngdbuild(config, target, log, subprocesses, prefix='.') -> int:
log(" - parsing options")
device = config.get(f'target.{target}', 'device', fallback='')
package = config.get(f'target.{target}', 'package', fallback='')
speedgrade = config.get(f'target.{target}', 'speedgrade', fallback='')
ngdbuild_opts = config.get(f'target.{target}', 'ngdbuild_opts', fallback='')
files_con = config.get(f'target.{target}', 'files_con', fallback='').split(' ')
build_dir = config.get(f'project', 'build_dir', fallback='build')
out_dir = config.get(f'project', 'out_dir', fallback='out')
devstring = f'{device}{speedgrade}-{package}'
prefix = f'{os.getcwd()}/{prefix}'
build_dir = f'{prefix}/{build_dir}'
out_dir = f'{prefix}/{out_dir}/{target}'
log(" - creating output directories")
os.makedirs(build_dir, exist_ok=True)
os.makedirs(out_dir, exist_ok=True)
log(" - run ngdbuild")
p = subprocess.Popen(f"ngdbuild -intstyle xflow -p {devstring} -uc {prefix}/{files_con[0]} {ngdbuild_opts} {out_dir}/{target}.ngc impl.ngd",
shell=True, cwd=build_dir,
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocesses.append(p)
while p.poll() is None:
time.sleep(1)
res = p.returncode
log(" - copy logs")
shutil.copy(f'{build_dir}/impl.bld', f'{out_dir}/ngdbuild.log')
if res==0:
log(" - copy output files")
shutil.copy(f'{build_dir}/impl.ngd', f'{out_dir}/{target}.ngd')
return res

View File

@ -0,0 +1,41 @@
import shutil
import os
import time
import subprocess
def par(config, target, log, subprocesses, prefix='.') -> int:
log(" - parsing options")
device = config.get(f'target.{target}', 'device', fallback='')
package = config.get(f'target.{target}', 'package', fallback='')
speedgrade = config.get(f'target.{target}', 'speedgrade', fallback='')
par_opts = config.get(f'target.{target}', 'par_opts', fallback='')
build_dir = config.get(f'project', 'build_dir', fallback='build')
out_dir = config.get(f'project', 'out_dir', fallback='out')
devstring = f'{device}{speedgrade}-{package}'
prefix = f'{os.getcwd()}/{prefix}'
build_dir = f'{prefix}/{build_dir}'
out_dir = f'{prefix}/{out_dir}/{target}'
log(" - creating output directories")
os.makedirs(build_dir, exist_ok=True)
os.makedirs(out_dir, exist_ok=True)
log(" - run par")
p = subprocess.Popen(f"par -intstyle xflow -ol high -xe n {par_opts} -w impl.map.ncd impl.pcf | tee par.log",
shell=True, cwd=build_dir,
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocesses.append(p)
while p.poll() is None:
time.sleep(1)
res = p.returncode
log(" - copy logs")
shutil.copy(f'{build_dir}/par.log', f'{out_dir}/par.log')
if res==0:
log(" - copy output files")
shutil.copy(f'{build_dir}/impl.pcf', f'{out_dir}/{target}.pcf')
shutil.copy(f'{build_dir}/impl.pcf.ncd', f'{out_dir}/{target}.ncd')
return res

View File

@ -0,0 +1,60 @@
import shutil
import os
import time
import subprocess
def xst(config, target, log, subprocesses, prefix='.') -> int:
log(" - parsing options")
device = config.get(f'target.{target}', 'device', fallback='')
package = config.get(f'target.{target}', 'package', fallback='')
speedgrade = config.get(f'target.{target}', 'speedgrade', fallback='')
toplevel = config.get(f'target.{target}', 'toplevel', fallback='toplevel')
xst_opts = config.get(f'target.{target}', 'xst_opts', fallback='')
files_vhdl = config.get(f'target.{target}', 'files_vhdl', fallback='').split(' ')
files_verilog = config.get(f'target.{target}', 'files_verilog', fallback='').split(' ')
build_dir = config.get(f'project', 'build_dir', fallback='build')
out_dir = config.get(f'project', 'out_dir', fallback='out')
devstring = f'{device}{speedgrade}-{package}'
prefix = f'{os.getcwd()}/{prefix}'
build_dir = f'{prefix}/{build_dir}'
out_dir = f'{prefix}/{out_dir}/{target}'
log(" - creating output directories")
os.makedirs(build_dir, exist_ok=True)
os.makedirs(out_dir, exist_ok=True)
log(" - writing project file")
with open(f'{build_dir}/syn.prj', 'w') as f:
for s in files_vhdl:
if s=='':
continue
f.write(f"vhdl work {prefix}/{s}\n")
for s in files_verilog:
if s=='':
continue
f.write(f"verilog work {prefix}/{s}\n")
log(" - writing project generation file")
with open(f'{build_dir}/prj.scr', 'w') as f:
f.write(f'run\n-ifn syn.prj\n-ofn syn.ngc\n-ifmt mixed\n')
f.write(f'-top {toplevel}\n')
f.write(f'-p {devstring}\n-glob_opt max_delay -opt_mode speed')
log(" - run xst")
p = subprocess.Popen(f"xst -intstyle xflow {xst_opts} -ifn prj.scr",
shell=True, cwd=build_dir,
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocesses.append(p)
while p.poll() is None:
time.sleep(1)
res = p.returncode
log(" - copy logs")
shutil.copy(f'{build_dir}/prj.srp', f'{out_dir}/xst.log')
if res==0:
log(" - copy output files")
shutil.copy(f'{build_dir}/syn.ngc', f'{out_dir}/{target}.ngc')
return res

View File

@ -5,34 +5,24 @@ import sys
def print_help(): def print_help():
print("Unified FPGA synthesizer frontend\r\n(c) Joppe Blondel - 2022\r\n") print("Unified FPGA synthesizer frontend\r\n(c) Joppe Blondel - 2022\r\n")
print(f"Usage: {sys.argv[0]} [ OPTIONS ] action [ target ] ...") print(f"Usage: {sys.argv[0]} [ OPTIONS ] target")
print("") print("")
print("Options:") print("Options:")
print(" -h Show this help message") print(" -h Show this help message")
print(" -c <file> Configuration file, defaults to project.cfg") print(" -c <file> Configuration file, defaults to project.cfg")
print("")
print("Actions:")
print("ip <target> Generate IP files from vendor provided libraries")
print("syn <target> Synthesize design for target")
print("impl <target> Route and place design for target")
print("bit <target> Generate output files and run analysis for target")
print("all <target> Generate IP, synthesize, route and place design for target")
print("floorplan <target> Run floorplan editor, currently only for local execution")
print("sim <simtarget> Run simulation target")
if __name__=="__main__": if __name__=="__main__":
# Parse arguments # Parse arguments
i = 1 i = 1
nextarg = None nextarg = None
configpath = 'project.cfg' configpath = 'project.cfg'
actions = [] target = ''
while i<len(sys.argv): while i<len(sys.argv):
if nextarg is not None: if nextarg is not None:
if nextarg=='config': if nextarg=='config':
configpath = sys.argv[i] configpath = sys.argv[i]
nextarg = None nextarg = None
else: else:
actions.append((nextarg, sys.argv[i]))
nextarg = None nextarg = None
elif sys.argv[i]=='-h': elif sys.argv[i]=='-h':
print_help() print_help()
@ -40,7 +30,7 @@ if __name__=="__main__":
elif sys.argv[i]=='-c': elif sys.argv[i]=='-c':
nextarg = 'config' nextarg = 'config'
else: else:
nextarg = sys.argv[i] target = sys.argv[i]
i += 1 i += 1
if nextarg is not None: if nextarg is not None:
print("ERROR: expected more arguments") print("ERROR: expected more arguments")
@ -52,32 +42,22 @@ if __name__=="__main__":
subprocesses = [] subprocesses = []
try: try:
for action in actions:
target = action[1]
action = action[0]
if not config.has_section(f'build:{target}'): toolchain = config.get(f'target.{target}', 'toolchain', fallback='NONE')
print("ERROR: config file has no build section for target") if toolchain=='NONE':
exit(1) print("ERROR: No toolchain specified for target")
devtarget = f'target:{config.get(f"build:{target}", "target", fallback="")}' exit(1)
if not config.has_section(devtarget):
print("ERROR: config file has no section for device target") try:
exit(1) exec(f"from remotesyn.toolchains.{toolchain} import do")
toolchain = config.get(devtarget, 'toolchain', fallback="NONE") except ImportError:
if toolchain=="NONE": print(f"ERROR: Unknown toolchain '{toolchain}'")
print("ERROR: no toolchain specified for device target") exit(1)
exit(1)
try:
exec(f"from remotesyn.{toolchain}.{action} import do")
except ImportError:
print(f"ERROR: Unknown action '{action}' for toolchain '{toolchain}'")
exit(1)
ret = do(config, target, print, subprocesses) ret = do(config, target, print, subprocesses)
if ret!=0: if ret!=0:
exit(ret) exit(ret)
except KeyboardInterrupt: except KeyboardInterrupt:
print("\rStopping rbuild") print("\rStopping rbuild")

View File

@ -64,6 +64,25 @@ def recv_file(channel, file):
f.write(channel.recv(1024)) f.write(channel.recv(1024))
fsize -= 1024 fsize -= 1024
def recv_dir(channel, dr):
cmd(b'ls'+sstr(dr), channel)
while True:
status = channel.recv(2)
if status != b'\x00\x00':
break
if status!=b'OK':
msg = channel.recv(1024)
print("Error:", bytes.decode(msg, 'ascii'))
exit(1)
ls = rstr(channel)
for p in ls.split('\n'):
tp = p[0]
name = p[1:]
if tp=='d':
recv_dir(channel, f'{dr}/{name}')
else:
recv_file(channel, f'{dr}/{name}')
def print_help(): def print_help():
print("Unified FPGA synthesizer frontend - remote execution\r\n(c) Joppe Blondel - 2022\r\n") print("Unified FPGA synthesizer frontend - remote execution\r\n(c) Joppe Blondel - 2022\r\n")
print(f"Usage: {sys.argv[0]} [ OPTIONS ] action [ target ] ...") print(f"Usage: {sys.argv[0]} [ OPTIONS ] action [ target ] ...")
@ -71,29 +90,19 @@ def print_help():
print("Options:") print("Options:")
print(" -h Show this help message") print(" -h Show this help message")
print(" -c <file> Configuration file, defaults to project.cfg") print(" -c <file> Configuration file, defaults to project.cfg")
print("")
print("Actions:")
print("ip <target> Generate IP files from vendor provided libraries")
print("syn <target> Synthesize design for target")
print("impl <target> Route and place design for target")
print("bit <target> Generate output files and run analysis for target")
print("all <target> Generate IP, synthesize, route and place design for target")
print("floorplan <target> Run floorplan editor, currently only for local execution")
print("sim <simtarget> Run simulation target")
if __name__=="__main__": if __name__=="__main__":
# Parse arguments # Parse arguments
i = 1 i = 1
nextarg = None nextarg = None
configpath = 'project.cfg' configpath = 'project.cfg'
actions = [] target = ''
while i<len(sys.argv): while i<len(sys.argv):
if nextarg is not None: if nextarg is not None:
if nextarg=='config': if nextarg=='config':
configpath = sys.argv[i] configpath = sys.argv[i]
nextarg = None nextarg = None
else: else:
actions.append((nextarg, sys.argv[i]))
nextarg = None nextarg = None
elif sys.argv[i]=='-h': elif sys.argv[i]=='-h':
print_help() print_help()
@ -101,7 +110,7 @@ if __name__=="__main__":
elif sys.argv[i]=='-c': elif sys.argv[i]=='-c':
nextarg = 'config' nextarg = 'config'
else: else:
nextarg = sys.argv[i] target = sys.argv[i]
i += 1 i += 1
if nextarg is not None: if nextarg is not None:
print("ERROR: expected more arguments") print("ERROR: expected more arguments")
@ -140,42 +149,32 @@ if __name__=="__main__":
subprocesses = [] subprocesses = []
try: try:
for action in actions:
target = action[1]
action = action[0]
if not config.has_section(f'build:{target}'): toolchain = config.get(f'target.{target}', 'toolchain', fallback='NONE')
print("ERROR: config file has no build section for target") if toolchain=='NONE':
exit(1) print("ERROR: No toolchain specified for target")
devtarget = f'target:{config.get(f"build:{target}", "target", fallback="")}' exit(1)
if not config.has_section(devtarget):
print("ERROR: config file has no section for device target") try:
exit(1) exec(f"from remotesyn.toolchains.{toolchain} import do")
toolchain = config.get(devtarget, 'toolchain', fallback="NONE") except ImportError:
if toolchain=="NONE": print(f"ERROR: Unknown toolchain '{toolchain}'")
print("ERROR: no toolchain specified for device target") exit(1)
exit(1)
try:
exec(f"from remotesyn.{toolchain}.{action} import do, needed_files, generated_files")
except ImportError:
print(f"ERROR: Unknown action '{action}' for toolchain '{toolchain}'")
exit(1)
# Send needed files # Send all files
for f in needed_files(config, target): for it in config.items(f"target.{target}"):
send_file(channel, f) if it[0].startswith('files_'):
for f in it[1].split():
send_file(channel, f)
# ret = do(config, target, print, subprocesses) cmd(b'do'+sstr(target), channel)
cmd(b'do'+sstr(f"{action} {target}"), channel) ret = 0
ret = 0
# Get generated files # Receive output dir
for f in generated_files(config, target): recv_dir(channel, config.get('project', 'out_dir', fallback='out'))
recv_file(channel, f)
if ret!=0: if ret!=0:
exit(ret) exit(ret)
except paramiko.ssh_exception.SSHException as e: except paramiko.ssh_exception.SSHException as e:
print("ERROR: Connection error...") print("ERROR: Connection error...")