sim: use Simulator as a contextmanager

__del__ garbage collector callbacks are too delicate.  E.g. imported
modules can be garbage collected before the objects using them. Can't
use os.remove, socket.SHUT_RDWR...

* added a DeprecationWarning if a Simulator is garbage collected without
having its .close() called
* renamed all gc __del__ callbacks to close()
* implemented context manager hooks for Simulator. Use like

   with Simulator(TestBench()) as s:
       s.run()
This commit is contained in:
Robert Jördens 2013-11-29 01:43:44 -07:00 committed by Sebastien Bourdeauducq
parent cf0fb5350f
commit 55afab2276
3 changed files with 23 additions and 2 deletions

View file

@ -1,3 +1,5 @@
import warnings
from migen.fhdl.std import *
from migen.fhdl.structure import _Fragment
from migen.fhdl import verilog
@ -177,9 +179,23 @@ class Simulator:
self.multiwrite(getattr(obj, k), v)
def __del__(self):
if hasattr(self, "ipc"):
warnings.warn("call Simulator.close() to clean up "
"or use it as a contextmanager", DeprecationWarning)
self.close()
def close(self):
self.ipc.close()
self.sim_runner.close()
del self.ipc
del self.sim_runner
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.close()
# Contrary to multiread/multiwrite, Proxy fetches the necessary signals only and
# immediately forwards writes into the simulation.
class Proxy:

View file

@ -3,6 +3,7 @@
import subprocess
import os
import time
def _str2file(filename, contents):
f = open(filename, "w")
@ -27,8 +28,12 @@ class Runner:
subprocess.check_call(["iverilog", "-o", self.vvp_file] + self.options + [self.top_file, self.dut_file] + self.extra_files)
self.process = subprocess.Popen(["vvp", "-mmigensim", self.vvp_file])
def __del__(self):
def close(self):
if hasattr(self, "process"):
self.process.terminate()
if self.process.poll() is None:
time.sleep(.1)
self.process.kill()
self.process.wait()
if not self.keep_files:
for f in [self.top_file, self.dut_file, self.vvp_file]:

View file

@ -166,7 +166,7 @@ class Initiator:
raise PacketTooLarge
return _unpack(packet)
def __del__(self):
def close(self):
if hasattr(self, "conn"):
self.conn.shutdown(socket.SHUT_RDWR)
self.conn.close()