diff --git a/remotesyn/toolchains/ISE.py b/remotesyn/toolchains/ISE.py index 8b37a62..da1d6b5 100644 --- a/remotesyn/toolchains/ISE.py +++ b/remotesyn/toolchains/ISE.py @@ -11,7 +11,7 @@ import shutil def do(config, target, log, subprocesses, prefix='.'): shutil.rmtree(config.get('project', 'build_dir', fallback='build'), True) - justsynth = config.getboolean(f'target.{target}', 'justsynth', fallback=False) + stopafter = config.get(f'target.{target}', 'stopafter', fallback='') log("Syntesize:") @@ -19,8 +19,7 @@ def do(config, target, log, subprocesses, prefix='.'): if res != 0: log("ERROR: xst returned with", res) return res - - if justsynth: + if stopafter=='synth': return res log("Implement") @@ -39,6 +38,8 @@ def do(config, target, log, subprocesses, prefix='.'): if res != 0: log("ERROR: par returned with", res) return res + if stopafter=='impl': + return res log("Generate output files") diff --git a/remotesyn/toolchains/cocotb.py b/remotesyn/toolchains/cocotb.py new file mode 100644 index 0000000..8f43167 --- /dev/null +++ b/remotesyn/toolchains/cocotb.py @@ -0,0 +1,83 @@ +from distutils.command.build import build +import shutil +import os +import time +import subprocess + +def do(config, target, log, subprocesses, prefix='.'): + shutil.rmtree(config.get('project', 'build_dir', fallback='build'), True) + + log("Starting cocotb") + + log(" - parsing options") + toplevels = config.get(f'target.{target}', 'toplevels', fallback='').split() + simulator = config.get(f'target.{target}', 'simulator', fallback='ghdl') + files_vhdl = config.get(f'target.{target}', 'files_vhdl', fallback='').split() + files_verilog = config.get(f'target.{target}', 'files_verilog', fallback='').split() + files_python = config.get(f'target.{target}', 'files_python', fallback='').split() + files_python_other = config.get(f'target.{target}', 'files_python_other', fallback='').split() + files_other = config.get(f'target.{target}', 'files_other', fallback='').split() + toplevel_langs = config.get(f'target.{target}', 'toplevel_langs', fallback='').split() + 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}%%'.replace('/.%%', '').replace('%%', '') + 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(" - copy needed files") + for f in files_python_other: + shutil.copy(f"{prefix}/{f}", f"{build_dir}/{os.path.basename(f)}") + for f in files_other: + d = os.path.dirname(f) + os.makedirs(f"{build_dir}/{d}", exist_ok=True) + shutil.copy(f"{prefix}/{f}", f"{build_dir}/{f}") + + res = 0 + + i = 0 + for pfile in files_python: + + log(" - copy", pfile) + shutil.copy(f"{prefix}/{pfile}", build_dir) + + log(" - writing Makefile for", pfile) + with open(f'{build_dir}/Makefile', 'w') as f: + f.write(f".SILENT:\nSIM ?= {simulator}\nTOPLEVEL_LANG ?= {toplevel_langs[i]}\nWAVES = 1\n") + f.write(f"TOPLEVEL = {toplevels[i]}\nMODULE = {'.'.join(os.path.basename(pfile).split('.')[0:-1])}\n") + for vfile in files_vhdl: + f.write(f"VHDL_SOURCES += {prefix}/{vfile}\n") + for vfile in files_verilog: + f.write(f"VERILOG_SOURCES += {prefix}/{vfile}\n") + + if simulator=='ghdl': + f.write(f"SIM_ARGS += --vcd={os.path.basename(pfile)}.vcd\n") + + f.write("include $(shell cocotb-config --makefiles)/Makefile.sim\n") + + log(" - start cocotb") + p = subprocess.Popen(f"make 2>&1 | tee {os.path.basename(pfile)}.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 + + shutil.copy(f"{build_dir}/{os.path.basename(pfile)}.log", out_dir) + + if simulator=='ghdl': + shutil.copy(f"{build_dir}/{os.path.basename(pfile)}.vcd", out_dir) + elif simulator=='questa': + os.system(f'wlf2vcd -o {out_dir}/{os.path.basename(pfile)}.vcd {build_dir}/vsim.wlf') + + i += 1 + + return res \ No newline at end of file diff --git a/remotesyn/toolchains/ghdl.py b/remotesyn/toolchains/ghdl.py index 1edfaf4..dc6bd44 100644 --- a/remotesyn/toolchains/ghdl.py +++ b/remotesyn/toolchains/ghdl.py @@ -6,7 +6,10 @@ import subprocess def execp(cmd, subprocesses, cwd): p = subprocess.Popen(cmd, shell=True, cwd=cwd, - stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + stdin=subprocess.DEVNULL, + #stdout=subprocess.DEVNULL, + #stderr=subprocess.DEVNULL + ) subprocesses.append(p) while p.poll() is None: time.sleep(1) @@ -67,7 +70,8 @@ def do(config, target, log, subprocesses, prefix='.'): extra = '' if runtime!='all': extra = f'--stop-time={runtime.replace(" ", "")}' - res = execp(f"echo {toplevel} >> r.log && ghdl -r {ghdlr_opts} {extra} {toplevel} --vcd=out.vcd 2>&1 1>> r.log", subprocesses, build_dir) + # res = execp(f"echo {toplevel} >> r.log && ghdl -r {ghdlr_opts} {toplevel} {extra} --vcd=out.vcd --wave=out.ghw 2>&1 | tee r.log", subprocesses, build_dir) + res = execp(f"echo {toplevel} >> r.log && ./{toplevel} {ghdlr_opts} {extra} --vcd=out.vcd --wave=out.ghw 2>&1 | tee r.log", subprocesses, build_dir) log(" - copy logs") shutil.copy(f'{build_dir}/r.log', f'{out_dir}/r.log') # Ignore simulation errors: vhdl stopping with failure results in returned with 1 @@ -77,5 +81,6 @@ def do(config, target, log, subprocesses, prefix='.'): log(" - copy output files") shutil.copy(f'{build_dir}/out.vcd', f'{out_dir}/out.vcd') + shutil.copy(f'{build_dir}/out.ghw', f'{out_dir}/out.ghw') - return 0 \ No newline at end of file + return 0 diff --git a/remotesyn/toolchains/isim.py b/remotesyn/toolchains/isim.py index 94ab41c..272f678 100644 --- a/remotesyn/toolchains/isim.py +++ b/remotesyn/toolchains/isim.py @@ -10,12 +10,13 @@ def do(config, target, log, subprocesses, prefix='.'): log(" - parsing options") toplevel = config.get(f'target.{target}', 'toplevel', fallback='toplevel') - vcdlevels = config.get(f'target.{target}', 'vcdlevels', fallback='1') + vcdlevels = config.get(f'target.{target}', 'vcdlevels', fallback='10') runtime = config.get(f'target.{target}', 'runtime', fallback='100 ns') fuse_opts = config.get(f'target.{target}', 'fuse_opts', fallback='') isim_opts = config.get(f'target.{target}', 'isim_opts', fallback='') files_vhdl = config.get(f'target.{target}', 'files_vhdl', fallback='').split() files_verilog = config.get(f'target.{target}', 'files_verilog', fallback='').split() + files_other = config.get(f'target.{target}', 'files_other', fallback='').split() build_dir = config.get(f'project', 'build_dir', fallback='build') out_dir = config.get(f'project', 'out_dir', fallback='out') @@ -30,6 +31,12 @@ def do(config, target, log, subprocesses, prefix='.'): os.makedirs(build_dir, exist_ok=True) os.makedirs(out_dir, exist_ok=True) + log(" - copy needed files") + for f in files_other: + d = os.path.dirname(f) + os.makedirs(f"{build_dir}/{d}", exist_ok=True) + shutil.copy(f"{prefix}/{f}", f"{build_dir}/{f}") + log(" - writing project file") with open(f'{build_dir}/sim.prj', 'w') as f: for s in files_vhdl: @@ -51,7 +58,7 @@ def do(config, target, log, subprocesses, prefix='.'): res = p.returncode log(" - copy logs") - shutil.copy(f'{build_dir}/ffuse.log', f'{out_dir}/fuse.log') + shutil.copy(f'{build_dir}/fuse.log', f'{out_dir}/fuse.log') if res!=0: log("ERROR: fuse returned with:", res) @@ -61,15 +68,18 @@ def do(config, target, log, subprocesses, prefix='.'): with open(f'{build_dir}/sim.tcl', 'w') as f: f.write("onerror {resume}\n") f.write("vcd dumpfile sim.vcd\n") - f.write(f"vcd dumpvars -m {toplevel} -l {vcdlevels}\n") + f.write(f"vcd dumpvars -m {toplevel.split()[0]} -l {vcdlevels}\n") f.write("vcd dumpon\n") f.write(f"run {runtime}\n") f.write("vcd dumpflush\nquit\n") log(" - run sim") - p = subprocess.Popen(f"./sim {isim_opts} -tclbatch sim.tcl > sim.log", + p = subprocess.Popen(f"./sim {isim_opts} -tclbatch sim.tcl | tee sim.log", shell=True, cwd=build_dir, - stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + stdin=subprocess.DEVNULL, + # stdout=subprocess.DEVNULL, + # stderr=subprocess.DEVNULL + ) subprocesses.append(p) while p.poll() is None: time.sleep(1) diff --git a/remotesyn/toolchains/make.py b/remotesyn/toolchains/make.py index cdc6c38..07df0d6 100644 --- a/remotesyn/toolchains/make.py +++ b/remotesyn/toolchains/make.py @@ -29,7 +29,10 @@ def do(config, target, log, subprocesses, prefix='.'): log(" - run make") p = subprocess.Popen(f"BUILDROOT={prefix}/{buildroot} make 2>make.log", shell=True, cwd=build_dir, - stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + stdin=subprocess.DEVNULL, + # stdout=subprocess.DEVNULL, + # stderr=subprocess.DEVNULL + ) subprocesses.append(p) while p.poll() is None: time.sleep(1) diff --git a/remotesyn/toolchains/questa.py b/remotesyn/toolchains/questa.py index 6bc9bad..b4ef0c5 100644 --- a/remotesyn/toolchains/questa.py +++ b/remotesyn/toolchains/questa.py @@ -12,6 +12,9 @@ def do(config, target, log, subprocesses, prefix='.'): log(" - parsing options") toplevel = config.get(f'target.{target}', 'toplevel', fallback='toplevel') runtime = config.get(f'target.{target}', 'runtime', fallback='100 ns') + vsim_opts = config.get(f'target.{target}', 'vsim_opts', fallback='') + vcom_opts = config.get(f'target.{target}', 'vcom_opts', fallback='') + vlog_opts = config.get(f'target.{target}', 'vlog_opts', fallback='') files_vhdl = config.get(f'target.{target}', 'files_vhdl', fallback='').split() files_verilog = config.get(f'target.{target}', 'files_verilog', fallback='').split() files_sysverilog = config.get(f'target.{target}', 'files_sysverilog', fallback='').split() @@ -28,31 +31,44 @@ def do(config, target, log, subprocesses, prefix='.'): os.makedirs(build_dir, exist_ok=True) os.makedirs(out_dir, exist_ok=True) + log(" - copy needed files") + for f in files_other: + d = os.path.dirname(f) + os.makedirs(f"{build_dir}/{d}", exist_ok=True) + shutil.copy(f"{prefix}/{f}", f"{build_dir}/{f}") + files_c_wp = {f'{prefix}/{f}' for f in files_c} log(" - writing compile file") with open(f'{build_dir}/do.sh', 'w') as f: f.write(f'vlib work\nvmap work work\n') - for s in files_vhdl: - f.write(f"vcom {prefix}/{s}\n") for s in files_verilog: - f.write(f"vlog {prefix}/{s}\n") + f.write(f"vlog {vlog_opts} {prefix}/{s}\n") + for s in files_vhdl: + f.write(f"vcom {vcom_opts} {prefix}/{s}\n") for s in files_sysverilog: - f.write(f"vlog -sv {prefix}/{s}\n") + f.write(f"vlog -sv {vlog_opts} {prefix}/{s}\n") f.write(f"gcc -g -fPIC -shared -Bsymbolic -o import.so {' '.join(files_c_wp)}\n") - extra = '' + extra = vsim_opts if len(files_c_wp)>0: - extra = '-sv_lib import' - f.write(f"vsim -c -do do.do {extra} {toplevel}") + extra = ' -sv_lib import' + f.write(f"vsim -c -do do.do {extra} -vcd=+multid+vhvar -vcddump=out.vcd {toplevel}") log(" - writing do file") + rtime = "-all" + if runtime != "all": + rtime = runtime with open(f'{build_dir}/do.do', 'w') as f: - f.write("vcd file out.vcd\n vcd add -r -in -out -inout -internal -ports *\nrun -all\nquit\n"); + # f.write(f"vcd file out.vcd\n vcd add -r -in -out -inout -internal -ports *\nrun {rtime}\nquit\n"); + f.write(f"\nrun {rtime}\nquit\n"); log(" - run vsim") p = subprocess.Popen(f"bash ./do.sh 2>&1 | tee do.log", shell=True, cwd=build_dir, - stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + stdin=subprocess.DEVNULL, + #stdout=subprocess.DEVNULL, + #stderr=subprocess.DEVNULL + ) subprocesses.append(p) while p.poll() is None: time.sleep(1) @@ -68,4 +84,4 @@ def do(config, target, log, subprocesses, prefix='.'): log(" - copy output files") shutil.copy(f'{build_dir}/out.vcd', f'{out_dir}/out.vcd') - return 0 \ No newline at end of file + return 0 diff --git a/remotesyn/toolchains/util_ISE/bitgen.py b/remotesyn/toolchains/util_ISE/bitgen.py index e03144b..5959e5f 100644 --- a/remotesyn/toolchains/util_ISE/bitgen.py +++ b/remotesyn/toolchains/util_ISE/bitgen.py @@ -20,7 +20,10 @@ def bitgen(config, target, log, subprocesses, prefix='.') -> int: log(" - run bitgen") p = subprocess.Popen(f"bitgen -intstyle xflow {bitgen_opts} -g Binary:Yes -w {out_dir}/{target}.ncd {target}.bit {out_dir}/{target}.pcf 2> bitgen.log", shell=True, cwd=build_dir, - stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + stdin=subprocess.DEVNULL, + # stdout=subprocess.DEVNULL, + # stderr=subprocess.DEVNULL + ) subprocesses.append(p) while p.poll() is None: time.sleep(1) diff --git a/remotesyn/toolchains/util_ISE/coregen.py b/remotesyn/toolchains/util_ISE/coregen.py index b5ec4cd..404b723 100644 --- a/remotesyn/toolchains/util_ISE/coregen.py +++ b/remotesyn/toolchains/util_ISE/coregen.py @@ -10,7 +10,7 @@ def coregen(config, target, log, subprocesses, prefix='.') -> int: package = config.get(f'target.{target}', 'package', fallback='') speedgrade = config.get(f'target.{target}', 'speedgrade', fallback='') coregen_opts = config.get(f'target.{target}', 'coregen_opts', fallback='') - files_xco = config.get(f'target.{target}', 'files_xco', fallback='').split() + files_def = config.get(f'target.{target}', 'files_def', fallback='').split() build_dir = config.get(f'project', 'build_dir', fallback='build') out_dir = config.get(f'project', 'out_dir', fallback='out') @@ -24,7 +24,7 @@ def coregen(config, target, log, subprocesses, prefix='.') -> int: res = 0 - for fxco in files_xco: + for fxco in files_def: cname = fxco.split('/')[-1].split('.')[0] log(" - Generating", cname, "...") @@ -40,6 +40,7 @@ def coregen(config, target, log, subprocesses, prefix='.') -> int: f.write(f'SET flowvendor = Other\n') f.write(f'SET verilogsim = true\n') f.write(f'SET vhdlsim = true\n') + f.write(f'SET implementationfiletype = ngc\n') log(" - run coregen") p = subprocess.Popen(f"coregen {coregen_opts} -p coregen_{cname}.cgp -b {prefix}/{fxco}", @@ -55,9 +56,22 @@ def coregen(config, target, log, subprocesses, prefix='.') -> int: if res==0: log(" - copy output files") - shutil.copy(f'{build_dir}/{cname}.vhd', f'{out_dir}/{cname}.vhd') - shutil.copy(f'{build_dir}/{cname}.v', f'{out_dir}/{cname}.v') - # shutil.copy(f'{build_dir}/{cname}.ngc', f'{out_dir}/{cname}.ngc') + try: + shutil.copy(f'{build_dir}/{cname}.vhd', f'{out_dir}/{cname}.vhd') + except FileNotFoundError: + pass + try: + shutil.copy(f'{build_dir}/{cname}.v', f'{out_dir}/{cname}.v') + except FileNotFoundError: + pass + try: + shutil.copy(f'{build_dir}/{cname}.ngc', f'{out_dir}/{cname}.ngc') + except FileNotFoundError: + pass + try: + shutil.copy(f'{build_dir}/{cname}.xco', f'{out_dir}/{cname}.xco') + except FileNotFoundError: + pass else: return res diff --git a/remotesyn/toolchains/util_ISE/map.py b/remotesyn/toolchains/util_ISE/map.py index 2bca7a4..645c588 100644 --- a/remotesyn/toolchains/util_ISE/map.py +++ b/remotesyn/toolchains/util_ISE/map.py @@ -24,7 +24,10 @@ def map(config, target, log, subprocesses, prefix='.') -> int: 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) + stdin=subprocess.DEVNULL, + # stdout=subprocess.DEVNULL, + # stderr=subprocess.DEVNULL + ) subprocesses.append(p) while p.poll() is None: time.sleep(1) diff --git a/remotesyn/toolchains/util_ISE/ngdbuild.py b/remotesyn/toolchains/util_ISE/ngdbuild.py index 3574d02..7e0c5c9 100644 --- a/remotesyn/toolchains/util_ISE/ngdbuild.py +++ b/remotesyn/toolchains/util_ISE/ngdbuild.py @@ -25,7 +25,10 @@ def ngdbuild(config, target, log, subprocesses, prefix='.') -> int: 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) + stdin=subprocess.DEVNULL, + # stdout=subprocess.DEVNULL, + # stderr=subprocess.DEVNULL + ) subprocesses.append(p) while p.poll() is None: time.sleep(1) diff --git a/remotesyn/toolchains/util_ISE/trce.py b/remotesyn/toolchains/util_ISE/trce.py index c251c60..9944356 100644 --- a/remotesyn/toolchains/util_ISE/trce.py +++ b/remotesyn/toolchains/util_ISE/trce.py @@ -28,5 +28,6 @@ def trce(config, target, log, subprocesses, prefix='.') -> int: log(" - copy logs") shutil.copy(f'{build_dir}/{target}.twr', f'{out_dir}/timing.log') + shutil.copy(f'{build_dir}/{target}.twx', f'{out_dir}/timing.twx') return res \ No newline at end of file diff --git a/remotesyn/toolchains/util_ISE/xst.py b/remotesyn/toolchains/util_ISE/xst.py index 25bce49..9447ceb 100644 --- a/remotesyn/toolchains/util_ISE/xst.py +++ b/remotesyn/toolchains/util_ISE/xst.py @@ -10,6 +10,8 @@ def xst(config, target, log, subprocesses, prefix='.') -> int: 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='') + netgensynth_opts = config.get(f'target.{target}', 'netgensynth_opts', fallback='-ofmt verilog') + netgensynth_type = config.get(f'target.{target}', 'netgensynth_type', fallback='-sim') 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') @@ -39,22 +41,52 @@ def xst(config, target, log, subprocesses, prefix='.') -> int: 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') + f.write(f'-p {devstring}\n-glob_opt max_delay -opt_mode speed\n') + f.write(f'-read_cores YES') 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) + 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==0: + log(" - copy output files") + shutil.copy(f'{build_dir}/syn.ngc', f'{out_dir}/{target}.ngc') + + log(" - run netgen") + extra = "" + if netgensynth_type=="-sim" and not netgensynth_opts.__contains__("-ofmt vhdl"): + extra = "-insert_glbl true -ism" + p = subprocess.Popen(f"netgen -intstyle xflow {netgensynth_type} -w {extra} {netgensynth_opts} {out_dir}/{target}.ngc 2>&1 >> prj.srp", + 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') + try: + shutil.copy(f'{build_dir}/{target}.v', f'{out_dir}/{target}-synth.v') + except FileNotFoundError: + pass + try: + shutil.copy(f'{build_dir}/{target}.vhd', f'{out_dir}/{target}-synth.vhd') + except FileNotFoundError: + pass return res \ No newline at end of file