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(" -c <file> Configuration file, defaults to project.cfg")
|
||||
|
||||
if __name__=="__main__":
|
||||
def main():
|
||||
# Parse arguments
|
||||
i = 1
|
||||
nextarg = None
|
||||
@ -73,13 +73,22 @@ if __name__=="__main__":
|
||||
exit(1)
|
||||
|
||||
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:
|
||||
log(f"ERROR: Unknown toolchain '{toolchain}'")
|
||||
exit(1)
|
||||
|
||||
ret = do(config, target, log, subprocesses)
|
||||
ret = do_func(config, target, log, subprocesses)
|
||||
|
||||
if ret!=0:
|
||||
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(" -c <file> Configuration file, defaults to project.cfg")
|
||||
|
||||
if __name__=="__main__":
|
||||
def main():
|
||||
# Parse arguments
|
||||
i = 1
|
||||
nextarg = None
|
||||
@ -220,4 +220,8 @@ if __name__=="__main__":
|
||||
print("ERROR: Connection error...", e)
|
||||
for p in subprocesses:
|
||||
p.kill()
|
||||
exit(0)
|
||||
exit(0)
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
main()
|
||||
@ -15,6 +15,7 @@ import threading
|
||||
import socket
|
||||
import shutil
|
||||
import fcntl
|
||||
import traceback
|
||||
|
||||
# List of running threads
|
||||
threads = []
|
||||
@ -209,6 +210,7 @@ class SSHServer(paramiko.ServerInterface):
|
||||
global running
|
||||
if running:
|
||||
print("ERROR: Unknown error:", e)
|
||||
traceback.print_exception(type(e), e, e.__traceback__)
|
||||
return False
|
||||
|
||||
class Connection(threading.Thread):
|
||||
@ -257,7 +259,9 @@ def print_help():
|
||||
print("Options:")
|
||||
print(" -h Show this help message")
|
||||
|
||||
if __name__=="__main__":
|
||||
def main():
|
||||
global running
|
||||
|
||||
# Parse arguments
|
||||
i = 1
|
||||
host = ''
|
||||
@ -307,4 +311,8 @@ if __name__=="__main__":
|
||||
|
||||
for t in threads:
|
||||
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')
|
||||
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')
|
||||
|
||||
@ -36,16 +37,23 @@ def xst(config, target, log, subprocesses, prefix='.') -> int:
|
||||
if s=='':
|
||||
continue
|
||||
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")
|
||||
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\n')
|
||||
f.write(f'-read_cores YES')
|
||||
f.write(xst_opts)
|
||||
f.write(f'\n-read_cores YES')
|
||||
|
||||
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,
|
||||
stdin=subprocess.DEVNULL,
|
||||
# stdout=subprocess.DEVNULL,
|
||||
|
||||
8
setup.py
8
setup.py
@ -21,5 +21,11 @@ setup(
|
||||
packages=['remotesyn'],
|
||||
licence='BSD Licence',
|
||||
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