sim: clean startup/shutdown

This commit is contained in:
Sebastien Bourdeauducq 2012-03-06 15:00:02 +01:00
parent 06de17b16c
commit 22b3c11b93
6 changed files with 43 additions and 20 deletions

View file

@ -4,16 +4,24 @@ from migen.sim.icarus import Runner
class Counter: class Counter:
def __init__(self): def __init__(self):
self.ce = Signal()
self.count = Signal(BV(4)) self.count = Signal(BV(4))
def do_simulation(self, s, cycle): def do_simulation(self, s, cycle):
if cycle % 2:
s.wr(self.ce, 0)
else:
s.wr(self.ce, 1)
print("Cycle: " + str(cycle) + " Count: " + str(s.rd(self.count))) print("Cycle: " + str(cycle) + " Count: " + str(s.rd(self.count)))
def get_fragment(self): def get_fragment(self):
sync = [self.count.eq(self.count + 1)] sync = [If(self.ce, self.count.eq(self.count + 1))]
sim = [self.do_simulation] sim = [self.do_simulation]
return Fragment(sync=sync, sim=sim) return Fragment(sync=sync, sim=sim)
def main():
dut = Counter() dut = Counter()
sim = Simulator(dut.get_fragment(), Runner()) sim = Simulator(dut.get_fragment(), Runner())
sim.run(10) sim.run(10)
main()

View file

@ -75,19 +75,19 @@ class Simulator:
self.sim_runner = sim_runner self.sim_runner = sim_runner
self.sim_runner.start(c_top, c_fragment) self.sim_runner.start(c_top, c_fragment)
self.ipc.accept() self.ipc.accept()
reply = self.ipc.recv()
self.fragment.call_sim(self, 0) assert(isinstance(reply, MessageTick))
self.ipc.send(MessageGo()) self.fragment.call_sim(self, -1)
def run(self, ncycles=-1): def run(self, ncycles=-1):
counter = 0 counter = 0
while not self.interrupt and (ncycles < 0 or counter < ncycles): while not self.interrupt and (ncycles < 0 or counter < ncycles):
self.ipc.send(MessageGo())
reply = self.ipc.recv() reply = self.ipc.recv()
assert(isinstance(reply, MessageTick)) assert(isinstance(reply, MessageTick))
self.fragment.call_sim(self, self.cycle_counter)
self.cycle_counter += 1 self.cycle_counter += 1
counter += 1 counter += 1
self.fragment.call_sim(self, self.cycle_counter)
self.ipc.send(MessageGo())
def rd(self, signal): def rd(self, signal):
name = self.top_level.top_name + "." \ name = self.top_level.top_name + "." \

View file

@ -20,9 +20,11 @@ class Runner:
_str2file(self.top_file, c_top) _str2file(self.top_file, c_top)
_str2file(self.dut_file, c_dut) _str2file(self.dut_file, c_dut)
subprocess.check_call(["iverilog", "-o", self.vvp_file, self.top_file, self.dut_file] + self.extra_files) subprocess.check_call(["iverilog", "-o", self.vvp_file, self.top_file, self.dut_file] + self.extra_files)
subprocess.Popen(["vvp", "-mmigensim", self.vvp_file]) self.process = subprocess.Popen(["vvp", "-mmigensim", self.vvp_file])
def __del__(self): def __del__(self):
if hasattr(self, "process"):
self.process.wait()
if not self.keep_files: if not self.keep_files:
for f in [self.top_file, self.dut_file, self.vvp_file]: for f in [self.top_file, self.dut_file, self.vvp_file]:
try: try:

View file

@ -145,7 +145,9 @@ class Initiator:
def __del__(self): def __del__(self):
if hasattr(self, "conn"): if hasattr(self, "conn"):
self.conn.shutdown(socket.SHUT_RDWR)
self.conn.close() self.conn.close()
if hasattr(self, "socket"): if hasattr(self, "socket"):
self.socket.shutdown(socket.SHUT_RDWR)
self.socket.close() self.socket.close()
self._cleanup_file() self._cleanup_file()

View file

@ -64,6 +64,11 @@ enum {
#define MAX_LEN 2048 #define MAX_LEN 2048
/*
* 0 -> error
* 1 -> success
* 2 -> graceful shutdown
*/
int ipc_receive(struct ipc_softc *sc) int ipc_receive(struct ipc_softc *sc)
{ {
char buffer[MAX_LEN]; char buffer[MAX_LEN];
@ -71,7 +76,9 @@ int ipc_receive(struct ipc_softc *sc)
int i; int i;
l = recv(sc->socket, buffer, MAX_LEN, 0); l = recv(sc->socket, buffer, MAX_LEN, 0);
if((l <= 0) || (l >= MAX_LEN)) if(l == 0)
return 2;
if((l < 0) || (l >= MAX_LEN))
return 0; return 0;
i = 0; i = 0;

View file

@ -105,10 +105,13 @@ static int h_read(char *name, void *user)
static int process_until_go(struct migensim_softc *sc) static int process_until_go(struct migensim_softc *sc)
{ {
int r;
sc->has_go = 0; sc->has_go = 0;
while(!sc->has_go) { while(!sc->has_go) {
if(!ipc_receive(sc->ipc)) r = ipc_receive(sc->ipc);
return 0; if(r != 1)
return r;
} }
return 1; return 1;
} }
@ -134,25 +137,26 @@ static PLI_INT32 connect_calltf(PLI_BYTE8 *user)
return 0; return 0;
} }
if(!process_until_go(sc)) {
vpi_control(vpiFinish, 1);
return 0;
}
return 0; return 0;
} }
static PLI_INT32 tick_calltf(PLI_BYTE8 *user) static PLI_INT32 tick_calltf(PLI_BYTE8 *user)
{ {
struct migensim_softc *sc = (struct migensim_softc *)user; struct migensim_softc *sc = (struct migensim_softc *)user;
int r;
if(!ipc_tick(sc->ipc)) { if(!ipc_tick(sc->ipc)) {
perror("ipc_tick"); perror("ipc_tick");
vpi_control(vpiFinish, 1); vpi_control(vpiFinish, 1);
ipc_destroy(sc->ipc);
sc->ipc = NULL;
return 0; return 0;
} }
if(!process_until_go(sc)) { r = process_until_go(sc);
vpi_control(vpiFinish, 1); if(r != 1) {
vpi_control(vpiFinish, r == 2 ? 0 : 1);
ipc_destroy(sc->ipc);
sc->ipc = NULL;
return 0; return 0;
} }