Skip to content

run_rtl: return simulator stdout and stderr outputs #105

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: v1.14_RC
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 46 additions & 4 deletions rtl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
from functools import reduce
import shutil
import re
import select
import io

#TheSyDeKick modules
if not (os.path.abspath('../../thesdk') in sys.path):
Expand Down Expand Up @@ -924,6 +926,8 @@ def execute_rtl_sim(self):
Add the probes in the simulation as you wish.
To finish the simulation, run the simulation to end and exit.""")

stdout = ""
stderr = ""
try:
if self.workdir:
self.print_log(type='I', msg=f"Executing in directory {self.workdir}")
Expand All @@ -933,13 +937,47 @@ def execute_rtl_sim(self):
execpath=self.rtlsimpath
self.print_log(type='I', msg="Running external command %s\n" %(self.rtlcmd) )
rtlcmd = f"cd {execpath} && {self._rtlcmd}"
output = subprocess.check_output(rtlcmd, shell=True)
self.print_log(type='I', msg='Simulator output:\n'+output.decode('utf-8'))
proc = subprocess.Popen(rtlcmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

# recode output streams to utf-8 so that we can read single unicode code points at a time. This should
# produce correct output character if a single character is encoded as multiple bytes.
try:
utf8_stdout = io.TextIOWrapper(proc.stdout, encoding='utf-8')
utf8_stderr = io.TextIOWrapper(proc.stderr, encoding='utf-8')
except Exception as e:
self.print_log(type='F', msg=f"Could not open simulator output stream: {e}")

# keep printing simulator output in real time until simulator process closes output streams
self.print_log(type='I', msg='Simulator output:\n')
while True:
# multiplex reads from stdout and stderr, print them, and append to respective variable
(rready, _, _) = select.select([utf8_stdout, utf8_stderr], [], [], 0.001)
for stream in rready:
# not the most efficient way to print out stuff, but we want to be able to see individual characters
# being printed out in real time, possibly without newlines, so print and flush one at a time.
codepoint = stream.read(1)
sys.stdout.write(codepoint)
sys.stdout.flush()
if stream == utf8_stdout:
stdout += codepoint
if stream == utf8_stderr:
stderr += codepoint

# wait for simulator process to terminate
try:
status = proc.wait(timeout=1e-6)
self.print_log(type='I', msg=f"Simulator exited with status code {status}")
# read any remaining output
stdout += utf8_stdout.read()
stderr += utf8_stderr.read()
break
except subprocess.TimeoutExpired:
pass

except subprocess.CalledProcessError as e:
output = e.output
self.print_log(type='F', msg='Simulator output:\n'+output.decode('utf-8'))


count=0
files_ok=False
while not files_ok:
Expand All @@ -952,6 +990,9 @@ def execute_rtl_sim(self):
files_ok=True
files_ok=files_ok and os.path.isfile(file.file)

# return simulator stdout and stderr logs for later analysis
return (stdout, stderr)


@property
def assignment_matchlist(self):
Expand Down Expand Up @@ -1024,7 +1065,7 @@ def run_rtl(self):
self.tb.generate_contents()
self.tb.export(force=True)
self.write_infile()
self.execute_rtl_sim()
(stdout, stderr) = self.execute_rtl_sim()
self.read_outfile()
self.connect_outputs()
# Save entity state
Expand All @@ -1034,6 +1075,7 @@ def run_rtl(self):
self.delete_iofile_bundle()
self.delete_rtlworkpath()
self.delete_rtlsimpath()
return (stdout, stderr)

#This writes all infile
def write_infile(self):
Expand Down