Compare commits

..

3 Commits

Author SHA1 Message Date
dc437c99ca Added iverilog 2025-10-08 16:44:52 +02:00
cc34f33d92 Fixed issues 2025-02-21 14:54:20 +01:00
7ce84f5637 Moved scripts to module 2025-02-21 13:56:31 +01:00
6 changed files with 168 additions and 11 deletions

View File

@ -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)
if __name__=="__main__":
main()

View File

@ -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
@ -221,3 +221,7 @@ if __name__=="__main__":
for p in subprocesses:
p.kill()
exit(0)
if __name__=="__main__":
main()

View File

@ -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 = ''
@ -308,3 +312,7 @@ if __name__=="__main__":
for t in threads:
t.join()
t.clean()
if __name__=="__main__":
main()

View 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

View File

@ -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,

View File

@ -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'
],
},
)