diff --git a/examples/spartan6/project.cfg b/examples/spartan6/project.cfg index 4713135..1fb52fa 100644 --- a/examples/spartan6/project.cfg +++ b/examples/spartan6/project.cfg @@ -1,26 +1,30 @@ [project] -name = spartan6_project -version = 0.1 -out_dir = OUT -build_dir = BUILD +name = spartan6_project +version = 0.1 +out_dir = OUT +build_dir = BUILD [server] -hostname = localhost -port = 2020 -privkey = /home/joppe/.ssh/id_rsa -pubkey = /home/joppe/.ssh/id_rsa.pub +hostname = localhost +port = 2020 +privkey = /home/joppe/.ssh/id_rsa +pubkey = /home/joppe/.ssh/id_rsa.pub -[target:default] -family = spartan6 -device = xc6slx9 -package = tqg144 -speedgrade = -2 -toolchain = ISE +[target.synth] +toolchain = ISE -[build:default] -target = default -toplevel = toplevel -constraints = CON/toplevel.ucf -src_vhdl = RTL/toplevel.vhd -src_verilog = -src_sysverilog = \ No newline at end of file +# Toolchain settings +family = spartan6 +device = xc6slx9 +package = tqg144 +speedgrade = -2 +toplevel = toplevel +#xst_opts = +#ngdbuild_opts = +#map_opts = +#par_opts = + +# Fileset +files_vhdl = RTL/toplevel.vhd +#files_verilog = +files_con = CON/toplevel.ucf \ No newline at end of file diff --git a/remotesyn/ISE/impl.py b/remotesyn/ISE/impl.py deleted file mode 100644 index 9d24bdc..0000000 --- a/remotesyn/ISE/impl.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/remotesyn/ISE/syn.py b/remotesyn/ISE/syn.py deleted file mode 100644 index caa121c..0000000 --- a/remotesyn/ISE/syn.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/remotesyn/toolchains/ISE.py b/remotesyn/toolchains/ISE.py new file mode 100644 index 0000000..462236d --- /dev/null +++ b/remotesyn/toolchains/ISE.py @@ -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 \ No newline at end of file diff --git a/remotesyn/ISE/__init__.py b/remotesyn/toolchains/__init__.py similarity index 100% rename from remotesyn/ISE/__init__.py rename to remotesyn/toolchains/__init__.py diff --git a/remotesyn/toolchains/util_ISE/__init__.py b/remotesyn/toolchains/util_ISE/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/remotesyn/toolchains/util_ISE/map.py b/remotesyn/toolchains/util_ISE/map.py new file mode 100644 index 0000000..2bca7a4 --- /dev/null +++ b/remotesyn/toolchains/util_ISE/map.py @@ -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 \ No newline at end of file diff --git a/remotesyn/toolchains/util_ISE/netgen.py b/remotesyn/toolchains/util_ISE/netgen.py new file mode 100644 index 0000000..c3d55d1 --- /dev/null +++ b/remotesyn/toolchains/util_ISE/netgen.py @@ -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 \ No newline at end of file diff --git a/remotesyn/toolchains/util_ISE/ngdbuild.py b/remotesyn/toolchains/util_ISE/ngdbuild.py new file mode 100644 index 0000000..24be64e --- /dev/null +++ b/remotesyn/toolchains/util_ISE/ngdbuild.py @@ -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 \ No newline at end of file diff --git a/remotesyn/toolchains/util_ISE/par.py b/remotesyn/toolchains/util_ISE/par.py new file mode 100644 index 0000000..2d93014 --- /dev/null +++ b/remotesyn/toolchains/util_ISE/par.py @@ -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 \ No newline at end of file diff --git a/remotesyn/toolchains/util_ISE/xst.py b/remotesyn/toolchains/util_ISE/xst.py new file mode 100644 index 0000000..45342b8 --- /dev/null +++ b/remotesyn/toolchains/util_ISE/xst.py @@ -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 \ No newline at end of file diff --git a/scripts/rbuild b/scripts/rbuild index c3b7fcd..f06424a 100755 --- a/scripts/rbuild +++ b/scripts/rbuild @@ -5,34 +5,24 @@ import sys def print_help(): 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("Options:") print(" -h Show this help message") print(" -c Configuration file, defaults to project.cfg") - print("") - print("Actions:") - print("ip Generate IP files from vendor provided libraries") - print("syn Synthesize design for target") - print("impl Route and place design for target") - print("bit Generate output files and run analysis for target") - print("all Generate IP, synthesize, route and place design for target") - print("floorplan Run floorplan editor, currently only for local execution") - print("sim Run simulation target") if __name__=="__main__": # Parse arguments i = 1 nextarg = None configpath = 'project.cfg' - actions = [] + target = '' while i Configuration file, defaults to project.cfg") - print("") - print("Actions:") - print("ip Generate IP files from vendor provided libraries") - print("syn Synthesize design for target") - print("impl Route and place design for target") - print("bit Generate output files and run analysis for target") - print("all Generate IP, synthesize, route and place design for target") - print("floorplan Run floorplan editor, currently only for local execution") - print("sim Run simulation target") if __name__=="__main__": # Parse arguments i = 1 nextarg = None configpath = 'project.cfg' - actions = [] + target = '' while i