Compare commits

..

10 Commits

Author SHA1 Message Date
Joppe Blondel
58a759e00c Fixedcoregen ISE 2025-10-19 15:36:10 +02:00
Joppe Blondel
ce90d68554 Added possibility to start from ngc in ISE build 2025-10-18 21:56:05 +02:00
Jojojoppe
dc437c99ca Added iverilog 2025-10-08 16:44:52 +02:00
Jojojoppe
cc34f33d92 Fixed issues 2025-02-21 14:54:20 +01:00
Jojojoppe
7ce84f5637 Moved scripts to module 2025-02-21 13:56:31 +01:00
Jojojoppe
84695d44b4 Added base GOWIN eda script 2023-10-14 20:30:45 +02:00
Joppe Blondel
da27f38f0f Added all subtle changes
Signed-off-by: Joppe Blondel <joppe@blondel.nl>
2022-10-14 21:39:56 +02:00
Jojojoppe
646440493f Return value acquisition from rmbuild fixed
Signed-off-by: Jojojoppe <joppe@blondel.nl>
2022-09-14 21:55:54 +02:00
Joppe Blondel
78205b90f2 Some small bug fixes in toolchains
Signed-off-by: Joppe Blondel <joppe@blondel.nl>
2022-09-14 21:40:52 +02:00
Joppe Blondel
1e8986f8a7 Fixed small bug in cosim.c
Signed-off-by: Joppe Blondel <joppe@blondel.nl>
2022-09-09 17:59:31 +02:00
25 changed files with 621 additions and 55 deletions

2
examples/GW1NSR-4C/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
OUT
BUILD

View File

@@ -0,0 +1,8 @@
IO_LOC "led_o" 10;
IO_PORT "led_o" PULL_MODE=NONE DRIVE=8;
IO_LOC "reset_n_i" 15;
IO_PORT "reset_n_i" PULL_MODE=UP;
IO_LOC "clk_i" 45;
IO_PORT "clk_i" PULL_MODE=UP;

View File

@@ -0,0 +1 @@
create_clock -name CLK_IN -period 37.037 -waveform {0 18.52} [get_ports {clk_i}]

View File

@@ -0,0 +1,23 @@
module led_blink
(
input clk_i,
input reset_n_i,
output led_o
);
reg [23:0] counter;
reg polarity;
always@(posedge clk_i) begin
if (!reset_n_i)
counter <= 24'h00000;
else
counter <= counter + 1'b1;
if (counter == 24'hFFFFF)
polarity <= ~polarity;
end
assign led_o = polarity;
endmodule

View File

@@ -0,0 +1,28 @@
[project]
name = gowin_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
# ######################################
# Basic synthesis
[target.synth]
toolchain = gowin
# Toolchain settings
family = GW1NSR-4C
device = GW1NSR-LV4CQN48PC6/I5
toplevel = led_blink
# Fileset
# files_vhdl =
files_verilog = RTL/toplevel.v
files_con = CON/io.cst
CON/io.sdc
# ######################################

View File

@@ -40,7 +40,7 @@ int start_cosim(char * descr){
void end_cosim(){ void end_cosim(){
close(fd); close(fd);
fclose(log); // fclose(log);
} }
int wait_cosim(uint32_t * retaddr, uint32_t * time){ int wait_cosim(uint32_t * retaddr, uint32_t * time){

View File

@@ -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()

View File

@@ -69,9 +69,10 @@ def recv_dir(channel, dr):
print("<<<", dr) print("<<<", dr)
cmd(b'ls'+sstr(dr), channel) cmd(b'ls'+sstr(dr), channel)
while True: while True:
status = channel.recv(2) status = channel.recv(1)
if status != b'\x00\x00': if status != b'\x00':
break break
status += channel.recv(1)
if status!=b'OK': if status!=b'OK':
msg = channel.recv(1024) msg = channel.recv(1024)
print("Error:", bytes.decode(msg, 'ascii')) print("Error:", bytes.decode(msg, 'ascii'))
@@ -95,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
@@ -170,7 +171,7 @@ if __name__=="__main__":
# Send config # Send config
cmd(b'cf' + sstr(json.dumps({s:dict(config.items(s)) for s in config.sections()})), channel) cmd(b'cf' + sstr(json.dumps({s:dict(config.items(s)) for s in config.sections()})), channel)
print("Target", target) print("LOCAL: Target", target)
toolchain = config.get(f'target.{target}', 'toolchain', fallback='NONE') toolchain = config.get(f'target.{target}', 'toolchain', fallback='NONE')
if toolchain=='NONE': if toolchain=='NONE':
@@ -190,7 +191,11 @@ if __name__=="__main__":
send_file(channel, f) send_file(channel, f)
cmd(b'do'+sstr(target), channel) cmd(b'do'+sstr(target), channel)
status = channel.recv(2) while True:
status = channel.recv(1)
if status!='b\x00':
break
status += channel.recv(1)
end = -1 end = -1
while end<0: while end<0:
data = channel.recv(8) data = channel.recv(8)
@@ -200,7 +205,7 @@ if __name__=="__main__":
print(str(data, 'utf-8'), end='', flush=True) print(str(data, 'utf-8'), end='', flush=True)
sys.stdout.flush() sys.stdout.flush()
ret = 0 ret = int.from_bytes(channel.recv(4), 'big')
# Receive output dir # Receive output dir
recv_dir(channel, config.get('project', 'out_dir', fallback='out')) recv_dir(channel, config.get('project', 'out_dir', fallback='out'))
@@ -216,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()

View File

@@ -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()

View File

@@ -11,12 +11,18 @@ import shutil
def do(config, target, log, subprocesses, prefix='.'): def do(config, target, log, subprocesses, prefix='.'):
shutil.rmtree(config.get('project', 'build_dir', fallback='build'), True) shutil.rmtree(config.get('project', 'build_dir', fallback='build'), True)
stopafter = config.get(f'target.{target}', 'stopafter', fallback='')
if config.get(f'target.{target}', 'ngc_in', fallback=None) is None:
# Synthesize if no ngc is already given
log("Syntesize:") log("Syntesize:")
res = xst(config, target, log, subprocesses, prefix) res = xst(config, target, log, subprocesses, prefix)
if res != 0: if res != 0:
log("ERROR: xst returned with", res) log("ERROR: xst returned with", res)
return res return res
if stopafter=='synth':
return res
log("Implement") log("Implement")
@@ -34,6 +40,8 @@ def do(config, target, log, subprocesses, prefix='.'):
if res != 0: if res != 0:
log("ERROR: par returned with", res) log("ERROR: par returned with", res)
return res return res
if stopafter=='impl':
return res
log("Generate output files") log("Generate output files")

View File

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

View File

@@ -6,7 +6,10 @@ import subprocess
def execp(cmd, subprocesses, cwd): def execp(cmd, subprocesses, cwd):
p = subprocess.Popen(cmd, p = subprocess.Popen(cmd,
shell=True, cwd=cwd, 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) subprocesses.append(p)
while p.poll() is None: while p.poll() is None:
time.sleep(1) time.sleep(1)
@@ -25,6 +28,7 @@ def do(config, target, log, subprocesses, prefix='.'):
ghdle_opts = config.get(f'target.{target}', 'ghdle_opts', fallback='') ghdle_opts = config.get(f'target.{target}', 'ghdle_opts', fallback='')
ghdlr_opts = config.get(f'target.{target}', 'ghdlr_opts', fallback='') ghdlr_opts = config.get(f'target.{target}', 'ghdlr_opts', fallback='')
files_vhdl = config.get(f'target.{target}', 'files_vhdl', 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(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,6 +40,12 @@ def do(config, target, log, subprocesses, prefix='.'):
os.makedirs(build_dir, exist_ok=True) os.makedirs(build_dir, exist_ok=True)
os.makedirs(out_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(" - analyze files") log(" - analyze files")
res = 0 res = 0
for f in files_vhdl: for f in files_vhdl:
@@ -60,7 +70,8 @@ def do(config, target, log, subprocesses, prefix='.'):
extra = '' extra = ''
if runtime!='all': if runtime!='all':
extra = f'--stop-time={runtime.replace(" ", "")}' 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") log(" - copy logs")
shutil.copy(f'{build_dir}/r.log', f'{out_dir}/r.log') shutil.copy(f'{build_dir}/r.log', f'{out_dir}/r.log')
# Ignore simulation errors: vhdl stopping with failure results in returned with 1 # Ignore simulation errors: vhdl stopping with failure results in returned with 1
@@ -70,5 +81,6 @@ def do(config, target, log, subprocesses, prefix='.'):
log(" - copy output files") log(" - copy output files")
shutil.copy(f'{build_dir}/out.vcd', f'{out_dir}/out.vcd') 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 return 0

View File

@@ -0,0 +1,135 @@
import shutil
import os
import time
import subprocess
import html2text
def do(config, target, log, subprocesses, prefix='.'):
shutil.rmtree(config.get('project', 'build_dir', fallback='build'), True)
shutil.rmtree(config.get('project', 'out_dir', fallback='out'), True)
log(" - parsing options")
family = config.get(f'target.{target}', 'family', fallback='')
device = config.get(f'target.{target}', 'device', fallback='')
toplevel = config.get(f'target.{target}', 'toplevel', fallback='toplevel')
files_vhdl = config.get(f'target.{target}', 'files_vhdl', fallback='').split()
files_verilog = config.get(f'target.{target}', 'files_verilog', fallback='').split()
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')
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 scripts")
with open(f'{build_dir}/synth.tcl', 'w') as f:
f.write(f'set_device {device} -name {family}\n')
for s in files_vhdl:
if s=='':
continue
f.write(f'add_file {prefix}/{s}\n')
for s in files_verilog:
if s=='':
continue
f.write(f'add_file {prefix}/{s}\n')
for s in files_con:
if s=='':
continue
f.write(f'add_file {prefix}/{s}\n')
f.write('set_option -synthesis_tool gowinsynthesis\n')
f.write(f'set_option -output_base_name {toplevel}\n')
f.write(f'set_option -top_module {toplevel}\n')
f.write('run syn\n')
with open(f'{build_dir}/pnr.tcl', 'w') as f:
f.write(f'set_device {device} -name {family}\n')
f.write('set_option -synthesis_tool gowinsynthesis\n')
f.write(f'set_option -output_base_name {toplevel}\n')
f.write(f'set_option -top_module {toplevel}\n')
for s in files_con:
if s=='':
continue
f.write(f'add_file {prefix}/{s}\n')
f.write(f'add_file {build_dir}/impl/gwsynthesis/{toplevel}.vg\n')
f.write('run pnr\n')
log(' - run syntesis')
p = subprocess.Popen(f"gw_sh synth.tcl",
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}/impl/gwsynthesis/{toplevel}.log', f'{out_dir}/synth.log')
if res!=0:
log("ERROR: synthesis failed with:", res)
return res
shutil.copy(f'{build_dir}/impl/gwsynthesis/{toplevel}.vg', f'{out_dir}/synth_netlist.vg')
with open(f'{build_dir}/impl/gwsynthesis/{toplevel}_syn.rpt.html', 'r') as fin, open(f'{out_dir}/synth_rpt.md', 'w') as fout:
text_maker = html2text.HTML2Text()
text_maker.bypass_tables = False
text_maker.ignore_links = True
text_maker.body_width = 500
fout.write(text_maker.handle(fin.read()))
log(' - run PnR')
p = subprocess.Popen(f"gw_sh pnr.tcl",
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}/impl/pnr/{toplevel}.log', f'{out_dir}/pnr.log')
if res!=0:
log("ERROR: pnr failed with:", res)
return res
shutil.copy(f'{build_dir}/impl/pnr/{toplevel}.fs', f'{out_dir}/{toplevel}.fs')
shutil.copy(f'{build_dir}/impl/pnr/{toplevel}.bin', f'{out_dir}/{toplevel}.bin')
with open(f'{build_dir}/impl/pnr/{toplevel}.rpt.html', 'r') as fin, open(f'{out_dir}/rpt.md', 'w') as fout:
text_maker = html2text.HTML2Text()
text_maker.bypass_tables = False
text_maker.ignore_links = True
text_maker.body_width = 500
fout.write(text_maker.handle(fin.read()))
with open(f'{build_dir}/impl/pnr/{toplevel}.power.html', 'r') as fin, open(f'{out_dir}/power.md', 'w') as fout:
text_maker = html2text.HTML2Text()
text_maker.bypass_tables = False
text_maker.ignore_links = True
text_maker.body_width = 500
fout.write(text_maker.handle(fin.read()))
with open(f'{build_dir}/impl/pnr/{toplevel}.pin.html', 'r') as fin, open(f'{out_dir}/pin.md', 'w') as fout:
text_maker = html2text.HTML2Text()
text_maker.bypass_tables = False
text_maker.ignore_links = True
text_maker.body_width = 500
fout.write(text_maker.handle(fin.read()))
with open(f'{build_dir}/impl/pnr/{toplevel}_tr_content.html', 'r') as fin, open(f'{out_dir}/timing.md', 'w') as fout:
text_maker = html2text.HTML2Text()
text_maker.bypass_tables = False
text_maker.ignore_links = True
text_maker.body_width = 500
fout.write(text_maker.handle(fin.read()))
return res

View File

@@ -10,12 +10,13 @@ def do(config, target, log, subprocesses, prefix='.'):
log(" - parsing options") log(" - parsing options")
toplevel = config.get(f'target.{target}', 'toplevel', fallback='toplevel') 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') runtime = config.get(f'target.{target}', 'runtime', fallback='100 ns')
fuse_opts = config.get(f'target.{target}', 'fuse_opts', fallback='') fuse_opts = config.get(f'target.{target}', 'fuse_opts', fallback='')
isim_opts = config.get(f'target.{target}', 'isim_opts', fallback='') isim_opts = config.get(f'target.{target}', 'isim_opts', fallback='')
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')
@@ -30,6 +31,12 @@ def do(config, target, log, subprocesses, prefix='.'):
os.makedirs(build_dir, exist_ok=True) os.makedirs(build_dir, exist_ok=True)
os.makedirs(out_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") log(" - writing project file")
with open(f'{build_dir}/sim.prj', 'w') as f: with open(f'{build_dir}/sim.prj', 'w') as f:
for s in files_vhdl: for s in files_vhdl:
@@ -51,7 +58,7 @@ def do(config, target, log, subprocesses, prefix='.'):
res = p.returncode res = p.returncode
log(" - copy logs") 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: if res!=0:
log("ERROR: fuse returned with:", res) 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: with open(f'{build_dir}/sim.tcl', 'w') as f:
f.write("onerror {resume}\n") f.write("onerror {resume}\n")
f.write("vcd dumpfile sim.vcd\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("vcd dumpon\n")
f.write(f"run {runtime}\n") f.write(f"run {runtime}\n")
f.write("vcd dumpflush\nquit\n") f.write("vcd dumpflush\nquit\n")
log(" - run sim") 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, 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) subprocesses.append(p)
while p.poll() is None: while p.poll() is None:
time.sleep(1) time.sleep(1)

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

@@ -29,7 +29,10 @@ def do(config, target, log, subprocesses, prefix='.'):
log(" - run make") log(" - run make")
p = subprocess.Popen(f"BUILDROOT={prefix}/{buildroot} make 2>make.log", p = subprocess.Popen(f"BUILDROOT={prefix}/{buildroot} make 2>make.log",
shell=True, cwd=build_dir, 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) subprocesses.append(p)
while p.poll() is None: while p.poll() is None:
time.sleep(1) time.sleep(1)

View File

@@ -12,6 +12,9 @@ def do(config, target, log, subprocesses, prefix='.'):
log(" - parsing options") log(" - parsing options")
toplevel = config.get(f'target.{target}', 'toplevel', fallback='toplevel') toplevel = config.get(f'target.{target}', 'toplevel', fallback='toplevel')
runtime = config.get(f'target.{target}', 'runtime', fallback='100 ns') 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_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_sysverilog = config.get(f'target.{target}', 'files_sysverilog', 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(build_dir, exist_ok=True)
os.makedirs(out_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} files_c_wp = {f'{prefix}/{f}' for f in files_c}
log(" - writing compile file") log(" - writing compile file")
with open(f'{build_dir}/do.sh', 'w') as f: with open(f'{build_dir}/do.sh', 'w') as f:
f.write(f'vlib work\nvmap work work\n') 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: 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: 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") 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: if len(files_c_wp)>0:
extra = '-sv_lib import' extra = ' -sv_lib import'
f.write(f"vsim -c -do do.do {extra} {toplevel}") f.write(f"vsim -c -do do.do {extra} -vcd=+multid+vhvar -vcddump=out.vcd {toplevel}")
log(" - writing do file") log(" - writing do file")
rtime = "-all"
if runtime != "all":
rtime = runtime
with open(f'{build_dir}/do.do', 'w') as f: with open(f'{build_dir}/do.do', 'w') as f:
f.write("vcd file out.vcd\n vcd add *\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") log(" - run vsim")
p = subprocess.Popen(f"bash ./do.sh 2>&1 | tee do.log", p = subprocess.Popen(f"bash ./do.sh 2>&1 | tee do.log",
shell=True, cwd=build_dir, 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) subprocesses.append(p)
while p.poll() is None: while p.poll() is None:
time.sleep(1) time.sleep(1)

View File

@@ -6,7 +6,9 @@ import subprocess
def execp(cmd, subprocesses, cwd): def execp(cmd, subprocesses, cwd):
p = subprocess.Popen(cmd, p = subprocess.Popen(cmd,
shell=True, cwd=cwd, 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) subprocesses.append(p)
while p.poll() is None: while p.poll() is None:
time.sleep(1) time.sleep(1)
@@ -55,7 +57,10 @@ def do(config, target, log, subprocesses, prefix='.'):
for d in os.listdir(f'{build_dir}'): for d in os.listdir(f'{build_dir}'):
if os.path.isdir(f'{build_dir}/{d}') and d.startswith(oname): if os.path.isdir(f'{build_dir}/{d}') and d.startswith(oname):
shutil.copy(f'{build_dir}/{d}/logfile.txt', f'{out_dir}/{d}.log') shutil.copy(f'{build_dir}/{d}/logfile.txt', f'{out_dir}/{d}.log')
try:
shutil.copytree(f'{build_dir}/{d}/engine_0', f'{out_dir}/{d}', dirs_exist_ok=True) shutil.copytree(f'{build_dir}/{d}/engine_0', f'{out_dir}/{d}', dirs_exist_ok=True)
except FileNotFoundError:
pass
if res!=0: if res!=0:
log(" - [-]") log(" - [-]")

View File

@@ -20,7 +20,10 @@ def bitgen(config, target, log, subprocesses, prefix='.') -> int:
log(" - run bitgen") 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", 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, 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) subprocesses.append(p)
while p.poll() is None: while p.poll() is None:
time.sleep(1) time.sleep(1)

View File

@@ -10,7 +10,7 @@ def coregen(config, target, log, subprocesses, prefix='.') -> int:
package = config.get(f'target.{target}', 'package', fallback='') package = config.get(f'target.{target}', 'package', fallback='')
speedgrade = config.get(f'target.{target}', 'speedgrade', fallback='') speedgrade = config.get(f'target.{target}', 'speedgrade', fallback='')
coregen_opts = config.get(f'target.{target}', 'coregen_opts', 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_xco', 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')
@@ -24,7 +24,7 @@ def coregen(config, target, log, subprocesses, prefix='.') -> int:
res = 0 res = 0
for fxco in files_xco: for fxco in files_def:
cname = fxco.split('/')[-1].split('.')[0] cname = fxco.split('/')[-1].split('.')[0]
log(" - Generating", cname, "...") 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 flowvendor = Other\n')
f.write(f'SET verilogsim = true\n') f.write(f'SET verilogsim = true\n')
f.write(f'SET vhdlsim = true\n') f.write(f'SET vhdlsim = true\n')
f.write(f'SET implementationfiletype = ngc\n')
log(" - run coregen") log(" - run coregen")
p = subprocess.Popen(f"coregen {coregen_opts} -p coregen_{cname}.cgp -b {prefix}/{fxco}", p = subprocess.Popen(f"coregen {coregen_opts} -p coregen_{cname}.cgp -b {prefix}/{fxco}",
@@ -55,9 +56,26 @@ def coregen(config, target, log, subprocesses, prefix='.') -> int:
if res==0: if res==0:
log(" - copy output files") log(" - copy output files")
try:
shutil.copy(f'{build_dir}/{cname}.vhd', f'{out_dir}/{cname}.vhd') 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') shutil.copy(f'{build_dir}/{cname}.v', f'{out_dir}/{cname}.v')
# shutil.copy(f'{build_dir}/{cname}.ngc', f'{out_dir}/{cname}.ngc') 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
try:
shutil.copy(f'{build_dir}/{cname}.ucf', f'{out_dir}/{cname}.ucf')
except FileNotFoundError:
pass
else: else:
return res return res

View File

@@ -24,7 +24,10 @@ def map(config, target, log, subprocesses, prefix='.') -> int:
log(" - run map") 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", 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, 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) subprocesses.append(p)
while p.poll() is None: while p.poll() is None:
time.sleep(1) time.sleep(1)

View File

@@ -22,10 +22,23 @@ def ngdbuild(config, target, log, subprocesses, prefix='.') -> int:
os.makedirs(build_dir, exist_ok=True) os.makedirs(build_dir, exist_ok=True)
os.makedirs(out_dir, exist_ok=True) os.makedirs(out_dir, exist_ok=True)
if config.get(f'target.{target}', 'ngc_in', fallback=None) is None:
ngcfile = f'{out_dir}/{target}.ngc'
else:
log(" - Synthesized design already given, start from there")
ngcfile = config.get(f'target.{target}', 'ngc_in', fallback='')
d = os.path.dirname(ngcfile)
if d:
os.makedirs(f"{build_dir}/{d}", exist_ok=True)
shutil.copy(ngcfile, f'{build_dir}/{ngcfile}')
log(" - run ngdbuild") 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", p = subprocess.Popen(f"ngdbuild -intstyle xflow -p {devstring} -uc {prefix}/{files_con[0]} {ngdbuild_opts} {ngcfile} impl.ngd",
shell=True, cwd=build_dir, 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) subprocesses.append(p)
while p.poll() is None: while p.poll() is None:
time.sleep(1) time.sleep(1)

View File

@@ -28,5 +28,6 @@ def trce(config, target, log, subprocesses, prefix='.') -> int:
log(" - copy logs") log(" - copy logs")
shutil.copy(f'{build_dir}/{target}.twr', f'{out_dir}/timing.log') 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 return res

View File

@@ -10,8 +10,11 @@ def xst(config, target, log, subprocesses, prefix='.') -> int:
speedgrade = config.get(f'target.{target}', 'speedgrade', fallback='') speedgrade = config.get(f'target.{target}', 'speedgrade', fallback='')
toplevel = config.get(f'target.{target}', 'toplevel', fallback='toplevel') toplevel = config.get(f'target.{target}', 'toplevel', fallback='toplevel')
xst_opts = config.get(f'target.{target}', 'xst_opts', fallback='') 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_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')
@@ -34,27 +37,64 @@ 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') f.write(f'-p {devstring}\n-glob_opt max_delay -opt_mode speed\n')
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, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) stdin=subprocess.DEVNULL,
# stdout=subprocess.DEVNULL,
# stderr=subprocess.DEVNULL
)
subprocesses.append(p) subprocesses.append(p)
while p.poll() is None: while p.poll() is None:
time.sleep(1) time.sleep(1)
res = p.returncode 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") log(" - copy logs")
shutil.copy(f'{build_dir}/prj.srp', f'{out_dir}/xst.log') shutil.copy(f'{build_dir}/prj.srp', f'{out_dir}/xst.log')
if res==0: if res==0:
log(" - copy output files") 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 return res

View File

@@ -20,6 +20,12 @@ setup(
], ],
packages=['remotesyn'], packages=['remotesyn'],
licence='BSD Licence', licence='BSD Licence',
install_requires=['paramiko'], 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'
],
},
) )