Compare commits
3 Commits
84695d44b4
...
dc437c99ca
| Author | SHA1 | Date | |
|---|---|---|---|
| dc437c99ca | |||
| cc34f33d92 | |||
| 7ce84f5637 |
@ -18,7 +18,7 @@ def print_help():
|
|||||||
log(" -h Show this help message")
|
log(" -h Show this help message")
|
||||||
log(" -c <file> Configuration file, defaults to project.cfg")
|
log(" -c <file> Configuration file, defaults to project.cfg")
|
||||||
|
|
||||||
if __name__=="__main__":
|
def main():
|
||||||
# Parse arguments
|
# Parse arguments
|
||||||
i = 1
|
i = 1
|
||||||
nextarg = None
|
nextarg = None
|
||||||
@ -73,13 +73,22 @@ if __name__=="__main__":
|
|||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
exec(f"from remotesyn.toolchains.{toolchain} import do")
|
print(f'Importing toolchain {toolchain}')
|
||||||
|
namespace = {}
|
||||||
|
exec(f"from remotesyn.toolchains.{toolchain} import do", globals(), namespace)
|
||||||
|
do_func = namespace.get('do')
|
||||||
|
if do_func is None:
|
||||||
|
raise ImportError("Failed to import 'do'")
|
||||||
except ImportError:
|
except ImportError:
|
||||||
log(f"ERROR: Unknown toolchain '{toolchain}'")
|
log(f"ERROR: Unknown toolchain '{toolchain}'")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
ret = do(config, target, log, subprocesses)
|
ret = do_func(config, target, log, subprocesses)
|
||||||
|
|
||||||
if ret!=0:
|
if ret!=0:
|
||||||
log("ERROR: toolchain returned with", ret)
|
log("ERROR: toolchain returned with", ret)
|
||||||
exit(ret)
|
exit(ret)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__=="__main__":
|
||||||
|
main()
|
||||||
@ -96,7 +96,7 @@ def print_help():
|
|||||||
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")
|
||||||
|
|
||||||
if __name__=="__main__":
|
def main():
|
||||||
# Parse arguments
|
# Parse arguments
|
||||||
i = 1
|
i = 1
|
||||||
nextarg = None
|
nextarg = None
|
||||||
@ -221,3 +221,7 @@ if __name__=="__main__":
|
|||||||
for p in subprocesses:
|
for p in subprocesses:
|
||||||
p.kill()
|
p.kill()
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__=="__main__":
|
||||||
|
main()
|
||||||
@ -15,6 +15,7 @@ import threading
|
|||||||
import socket
|
import socket
|
||||||
import shutil
|
import shutil
|
||||||
import fcntl
|
import fcntl
|
||||||
|
import traceback
|
||||||
|
|
||||||
# List of running threads
|
# List of running threads
|
||||||
threads = []
|
threads = []
|
||||||
@ -209,6 +210,7 @@ class SSHServer(paramiko.ServerInterface):
|
|||||||
global running
|
global running
|
||||||
if running:
|
if running:
|
||||||
print("ERROR: Unknown error:", e)
|
print("ERROR: Unknown error:", e)
|
||||||
|
traceback.print_exception(type(e), e, e.__traceback__)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
class Connection(threading.Thread):
|
class Connection(threading.Thread):
|
||||||
@ -257,7 +259,9 @@ def print_help():
|
|||||||
print("Options:")
|
print("Options:")
|
||||||
print(" -h Show this help message")
|
print(" -h Show this help message")
|
||||||
|
|
||||||
if __name__=="__main__":
|
def main():
|
||||||
|
global running
|
||||||
|
|
||||||
# Parse arguments
|
# Parse arguments
|
||||||
i = 1
|
i = 1
|
||||||
host = ''
|
host = ''
|
||||||
@ -308,3 +312,7 @@ if __name__=="__main__":
|
|||||||
for t in threads:
|
for t in threads:
|
||||||
t.join()
|
t.join()
|
||||||
t.clean()
|
t.clean()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__=="__main__":
|
||||||
|
main()
|
||||||
122
remotesyn/toolchains/iverilog.py
Normal file
122
remotesyn/toolchains/iverilog.py
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
# iverilog.py
|
||||||
|
import shutil
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def _execp(cmd, subprocesses, cwd):
|
||||||
|
p = subprocess.Popen(
|
||||||
|
cmd,
|
||||||
|
shell=True,
|
||||||
|
cwd=cwd,
|
||||||
|
stdin=subprocess.DEVNULL,
|
||||||
|
# stdout/stderr visible so tee can capture; keep quiet if you prefer:
|
||||||
|
# stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
||||||
|
)
|
||||||
|
subprocesses.append(p)
|
||||||
|
while p.poll() is None:
|
||||||
|
time.sleep(0.2)
|
||||||
|
return p.returncode
|
||||||
|
|
||||||
|
def do(config, target, log, subprocesses, prefix='.'):
|
||||||
|
# fresh build dir
|
||||||
|
shutil.rmtree(config.get('project', 'build_dir', fallback='build'), True)
|
||||||
|
|
||||||
|
log("Starting simulation (iverilog)")
|
||||||
|
|
||||||
|
# --- parse options (keep names consistent with your other toolchains) ---
|
||||||
|
toplevel = config.get(f'target.{target}', 'toplevel', fallback='toplevel')
|
||||||
|
ivl_opts = config.get(f'target.{target}', 'ivl_opts', fallback='')
|
||||||
|
vvp_opts = config.get(f'target.{target}', 'vvp_opts', fallback='')
|
||||||
|
runtime = config.get(f'target.{target}', 'runtime', fallback='') # optional; TB can honor +stop_time
|
||||||
|
files_verilog = config.get(f'target.{target}', 'files_verilog', fallback='').split()
|
||||||
|
files_sysverilog= config.get(f'target.{target}', 'files_sysverilog', fallback='').split()
|
||||||
|
files_vhdl = config.get(f'target.{target}', 'files_vhdl', fallback='').split()
|
||||||
|
files_other = config.get(f'target.{target}', 'files_other', fallback='').split()
|
||||||
|
build_dir = config.get('project', 'build_dir', fallback='build')
|
||||||
|
out_dir_root = config.get('project', 'out_dir', fallback='out')
|
||||||
|
|
||||||
|
# normalize paths
|
||||||
|
prefix = f'{os.getcwd()}/{prefix}'
|
||||||
|
build_dir= f'{prefix}/{build_dir}'
|
||||||
|
out_dir = f'{prefix}/{out_dir_root}/{target}'
|
||||||
|
|
||||||
|
# minor sanitization
|
||||||
|
ivl_opts = ivl_opts.replace('\n', ' ')
|
||||||
|
vvp_opts = vvp_opts.replace('\n', ' ')
|
||||||
|
|
||||||
|
# --- create dirs ---
|
||||||
|
log(" - creating output directories")
|
||||||
|
os.makedirs(build_dir, exist_ok=True)
|
||||||
|
os.makedirs(out_dir, exist_ok=True)
|
||||||
|
|
||||||
|
# --- copy extra needed files into build dir (keeping tree) ---
|
||||||
|
if files_other:
|
||||||
|
log(" - copy needed files")
|
||||||
|
for f in files_other:
|
||||||
|
if not f: continue
|
||||||
|
d = os.path.dirname(f)
|
||||||
|
if d:
|
||||||
|
os.makedirs(f"{build_dir}/{d}", exist_ok=True)
|
||||||
|
shutil.copy(f"{prefix}/{f}", f"{build_dir}/{f}")
|
||||||
|
|
||||||
|
# --- guard: VHDL not supported by Icarus ---
|
||||||
|
if any(s for s in files_vhdl if s.strip()):
|
||||||
|
log("WARNING: VHDL files listed but iverilog does not support VHDL — ignoring them")
|
||||||
|
|
||||||
|
# --- build source list (order as provided) ---
|
||||||
|
sources = []
|
||||||
|
for s in files_verilog:
|
||||||
|
if s: sources.append(f'"{prefix}/{s}"')
|
||||||
|
for s in files_sysverilog:
|
||||||
|
if s: sources.append(f'"{prefix}/{s}"')
|
||||||
|
|
||||||
|
if not sources:
|
||||||
|
log("ERROR: no Verilog/SystemVerilog sources provided")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# --- decide standard (enable SV if any sysverilog files or if user asked) ---
|
||||||
|
needs_sv = len([1 for _ in files_sysverilog if _]) > 0
|
||||||
|
std_flag = "-g2012" if needs_sv and "-g" not in ivl_opts and "-g2012" not in ivl_opts else ""
|
||||||
|
|
||||||
|
# --- compile ---
|
||||||
|
log(" - compile (iverilog)")
|
||||||
|
# -s <top> sets the toplevel; produce sim.vvp; tee compile log
|
||||||
|
# You can add include dirs/defines via ivl_opts (e.g., -Iinc -DNAME=VALUE)
|
||||||
|
cmd_compile = f'iverilog -o sim.vvp -s {toplevel} {std_flag} {ivl_opts} ' + " ".join(sources) + ' 2>&1 | tee comp.log'
|
||||||
|
res = _execp(cmd_compile, subprocesses, build_dir)
|
||||||
|
|
||||||
|
# logs
|
||||||
|
shutil.copy(f'{build_dir}/comp.log', f'{out_dir}/compile.log')
|
||||||
|
if res != 0:
|
||||||
|
log("ERROR: iverilog returned with", res)
|
||||||
|
return res
|
||||||
|
|
||||||
|
# --- simulate ---
|
||||||
|
log(" - simulate (vvp)")
|
||||||
|
# If your TB supports +stop_time=<time>, we pass it from 'runtime' (e.g., "1000us" -> +stop_time=1000us)
|
||||||
|
plusargs = []
|
||||||
|
if runtime and runtime.strip().lower() != 'all':
|
||||||
|
rt = runtime.replace(" ", "")
|
||||||
|
plusargs.append(f'+stop_time={rt}') # your TB can $value$plusargs("stop_time=%s", str)
|
||||||
|
|
||||||
|
cmd_run = f'vvp {vvp_opts} sim.vvp ' + " ".join(plusargs) + ' 2>&1 | tee sim.log'
|
||||||
|
res = _execp(cmd_run, subprocesses, build_dir)
|
||||||
|
|
||||||
|
# copy sim log
|
||||||
|
shutil.copy(f'{build_dir}/sim.log', f'{out_dir}/simulate.log')
|
||||||
|
|
||||||
|
# --- copy outputs if present ---
|
||||||
|
# Expect the TB to do $dumpfile("out.vcd"); $dumpvars; (or use your own filename)
|
||||||
|
vcd_candidates = ["out.vcd", f"{toplevel}.vcd", "sim.vcd"]
|
||||||
|
copied = False
|
||||||
|
for vcd in vcd_candidates:
|
||||||
|
src = f'{build_dir}/{vcd}'
|
||||||
|
if os.path.exists(src):
|
||||||
|
shutil.copy(src, f'{out_dir}/out.vcd')
|
||||||
|
copied = True
|
||||||
|
break
|
||||||
|
if not copied:
|
||||||
|
log("NOTE: no VCD found (ensure your TB calls $dumpfile(\"out.vcd\") and $dumpvars)")
|
||||||
|
|
||||||
|
return res
|
||||||
@ -14,6 +14,7 @@ def xst(config, target, log, subprocesses, prefix='.') -> int:
|
|||||||
netgensynth_type = config.get(f'target.{target}', 'netgensynth_type', fallback='-sim')
|
netgensynth_type = config.get(f'target.{target}', 'netgensynth_type', fallback='-sim')
|
||||||
files_vhdl = config.get(f'target.{target}', 'files_vhdl', fallback='').split()
|
files_vhdl = config.get(f'target.{target}', 'files_vhdl', fallback='').split()
|
||||||
files_verilog = config.get(f'target.{target}', 'files_verilog', 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')
|
build_dir = config.get(f'project', 'build_dir', fallback='build')
|
||||||
out_dir = config.get(f'project', 'out_dir', fallback='out')
|
out_dir = config.get(f'project', 'out_dir', fallback='out')
|
||||||
|
|
||||||
@ -36,16 +37,23 @@ def xst(config, target, log, subprocesses, prefix='.') -> int:
|
|||||||
if s=='':
|
if s=='':
|
||||||
continue
|
continue
|
||||||
f.write(f"verilog work {prefix}/{s}\n")
|
f.write(f"verilog work {prefix}/{s}\n")
|
||||||
|
for f in files_other:
|
||||||
|
if not f: continue
|
||||||
|
d = os.path.dirname(f)
|
||||||
|
if d:
|
||||||
|
os.makedirs(f"{build_dir}/{d}", exist_ok=True)
|
||||||
|
shutil.copy(f"{prefix}/{f}", f"{build_dir}/{f}")
|
||||||
|
|
||||||
log(" - writing project generation file")
|
log(" - writing project generation file")
|
||||||
with open(f'{build_dir}/prj.scr', 'w') as f:
|
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'run\n-ifn syn.prj\n-ofn syn.ngc\n-ifmt mixed\n')
|
||||||
f.write(f'-top {toplevel}\n')
|
f.write(f'-top {toplevel}\n')
|
||||||
f.write(f'-p {devstring}\n-glob_opt max_delay -opt_mode speed\n')
|
f.write(f'-p {devstring}\n-glob_opt max_delay -opt_mode speed\n')
|
||||||
f.write(f'-read_cores YES')
|
f.write(xst_opts)
|
||||||
|
f.write(f'\n-read_cores YES')
|
||||||
|
|
||||||
log(" - run xst")
|
log(" - run xst")
|
||||||
p = subprocess.Popen(f"xst -intstyle xflow {xst_opts} -ifn prj.scr",
|
p = subprocess.Popen(f"xst -intstyle xflow -ifn prj.scr",
|
||||||
shell=True, cwd=build_dir,
|
shell=True, cwd=build_dir,
|
||||||
stdin=subprocess.DEVNULL,
|
stdin=subprocess.DEVNULL,
|
||||||
# stdout=subprocess.DEVNULL,
|
# stdout=subprocess.DEVNULL,
|
||||||
|
|||||||
8
setup.py
8
setup.py
@ -21,5 +21,11 @@ setup(
|
|||||||
packages=['remotesyn'],
|
packages=['remotesyn'],
|
||||||
licence='BSD Licence',
|
licence='BSD Licence',
|
||||||
install_requires=['paramiko', 'html2text'],
|
install_requires=['paramiko', 'html2text'],
|
||||||
scripts=['scripts/rbuild', 'scripts/rmbuild', 'scripts/rmserver']
|
entry_points={
|
||||||
|
'console_scripts': [
|
||||||
|
'rmserver = remotesyn.rmserver:main',
|
||||||
|
'rmbuild = remotesyn.rmbuild:main',
|
||||||
|
'rbuild = remotesyn.rbuild:main'
|
||||||
|
],
|
||||||
|
},
|
||||||
)
|
)
|
||||||
Reference in New Issue
Block a user