From 8160ced2e9ce96b4fba3c109a3ca16c7734ff83f Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Tue, 6 Mar 2012 19:29:39 +0100 Subject: [PATCH] sim: memory access --- examples/basic_sim.py | 6 +++--- examples/memory_sim.py | 27 +++++++++++++++++++++++++++ migen/fhdl/structure.py | 4 ++-- migen/sim/generic.py | 40 +++++++++++++++++++++++++--------------- migen/sim/ipc.py | 24 ++++++++++++++++++++---- vpi/ipc.c | 13 +++++++++---- vpi/ipc.h | 4 ++-- vpi/main.c | 12 ++++++++++-- 8 files changed, 98 insertions(+), 32 deletions(-) create mode 100644 examples/memory_sim.py diff --git a/examples/basic_sim.py b/examples/basic_sim.py index 3578bc97..a4f17c46 100644 --- a/examples/basic_sim.py +++ b/examples/basic_sim.py @@ -7,12 +7,12 @@ class Counter: self.ce = Signal() self.count = Signal(BV(37, True), reset=-5) - def do_simulation(self, s, cycle): - if cycle % 2: + def do_simulation(self, s): + if s.cycle_counter % 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(s.cycle_counter) + " Count: " + str(s.rd(self.count))) def get_fragment(self): sync = [If(self.ce, self.count.eq(self.count + 1))] diff --git a/examples/memory_sim.py b/examples/memory_sim.py new file mode 100644 index 00000000..7c58b2bb --- /dev/null +++ b/examples/memory_sim.py @@ -0,0 +1,27 @@ +from migen.fhdl.structure import * +from migen.sim.generic import Simulator, TopLevel +from migen.sim.icarus import Runner + +class Mem: + def __init__(self): + self.a = Signal(BV(12)) + self.d = Signal(BV(16)) + p = MemoryPort(self.a, self.d) + self.mem = Memory(16, 2**12, p, init=list(range(20))) + + def do_simulation(self, s): + if s.cycle_counter >= 0: + value = s.rd(self.mem, s.cycle_counter) + print(value) + if value == 10: + s.interrupt = True + + def get_fragment(self): + return Fragment(memories=[self.mem], sim=[self.do_simulation]) + +def main(): + dut = Mem() + sim = Simulator(dut.get_fragment(), Runner()) + sim.run() + +main() diff --git a/migen/fhdl/structure.py b/migen/fhdl/structure.py index 21e5cb0e..e5730ff5 100644 --- a/migen/fhdl/structure.py +++ b/migen/fhdl/structure.py @@ -276,6 +276,6 @@ class Fragment: self.pads | other.pads, self.sim + other.sim) - def call_sim(self, simulator, cycle): + def call_sim(self, simulator): for s in self.sim: - s(simulator, cycle) + s(simulator) diff --git a/migen/sim/generic.py b/migen/sim/generic.py index 60057e1e..dddc7e41 100644 --- a/migen/sim/generic.py +++ b/migen/sim/generic.py @@ -84,7 +84,7 @@ class Simulator: rst_signal=rst_signal, return_ns=True) - self.cycle_counter = 0 + self.cycle_counter = -1 self.interrupt = False self.sim_runner = sim_runner @@ -92,36 +92,46 @@ class Simulator: self.ipc.accept() reply = self.ipc.recv() assert(isinstance(reply, MessageTick)) - self.fragment.call_sim(self, -1) + self.fragment.call_sim(self) def run(self, ncycles=-1): + self.interrupt = False counter = 0 while not self.interrupt and (ncycles < 0 or counter < ncycles): + self.cycle_counter += 1 + counter += 1 self.ipc.send(MessageGo()) reply = self.ipc.recv() assert(isinstance(reply, MessageTick)) - self.fragment.call_sim(self, self.cycle_counter) - self.cycle_counter += 1 - counter += 1 + self.fragment.call_sim(self) - def rd(self, signal): + def rd(self, item, index=0): name = self.top_level.top_name + "." \ + self.top_level.dut_name + "." \ - + self.namespace.get_name(signal) - self.ipc.send(MessageRead(name)) + + self.namespace.get_name(item) + self.ipc.send(MessageRead(name, Int32(index))) reply = self.ipc.recv() assert(isinstance(reply, MessageReadReply)) - nbits = signal.bv.width + if isinstance(item, Memory): + signed = False + nbits = item.width + else: + signed = item.bv.signed + nbits = item.bv.width value = reply.value & (2**nbits - 1) - if signal.bv.signed and (value & 2**(nbits - 1)): + if signed and (value & 2**(nbits - 1)): value -= 2**nbits return value - def wr(self, signal, value): + def wr(self, item, value, index=0): name = self.top_level.top_name + "." \ + self.top_level.dut_name + "." \ - + self.namespace.get_name(signal) + + self.namespace.get_name(item) + if isinstance(item, Memory): + nbits = item.width + else: + nbits = item.bv.width if value < 0: - value += 2**signal.bv.width - assert(value >= 0 and value < 2**signal.bv.width) - self.ipc.send(MessageWrite(name, value)) + value += 2**nbits + assert(value >= 0 and value < 2**nbits) + self.ipc.send(MessageWrite(name, Int32(index), value)) diff --git a/migen/sim/ipc.py b/migen/sim/ipc.py index 9464a12c..ca59c4f7 100644 --- a/migen/sim/ipc.py +++ b/migen/sim/ipc.py @@ -5,6 +5,9 @@ import os # Message classes # +class Int32(int): + pass + class Message: def __init__(self, *pvalues): for parameter, value in zip(self.parameters, pvalues): @@ -29,11 +32,11 @@ class MessageGo(Message): class MessageWrite(Message): code = 2 - parameters = [(str, "name"), (int, "value")] + parameters = [(str, "name"), (Int32, "index"), (int, "value")] class MessageRead(Message): code = 3 - parameters = [(str, "name")] + parameters = [(str, "name"), (Int32, "index")] class MessageReadReply(Message): code = 4 @@ -58,6 +61,14 @@ def _pack_str(v): p.append(0) return p +def _pack_int32(v): + return [ + v & 0xff, + (v & 0xff00) >> 8, + (v & 0xff0000) >> 16, + (v & 0xff000000) >> 24 + ] + def _pack(message): r = [message.code] for t, p in message.parameters: @@ -67,6 +78,8 @@ def _pack(message): r += _pack_int(value) elif t == str: r += _pack_str(value) + elif t == Int32: + r += _pack_int32(value) else: raise TypeError return bytes(r) @@ -75,10 +88,11 @@ def _pack(message): # Unpacking # -def _unpack_int(i): +def _unpack_int(i, nchunks=None): v = 0 power = 1 - nchunks = next(i) + if nchunks is None: + nchunks = next(i) for j in range(nchunks): v += power*next(i) power *= 256 @@ -102,6 +116,8 @@ def _unpack(message): v = _unpack_int(i) elif t == str: v = _unpack_str(i) + elif t == Int32: + v = _unpack_int(i, 4) else: raise TypeError pvalues.append(v) diff --git a/vpi/ipc.c b/vpi/ipc.c index c78fd20e..c76081d3 100644 --- a/vpi/ipc.c +++ b/vpi/ipc.c @@ -90,24 +90,29 @@ int ipc_receive(struct ipc_softc *sc) char *name; int nchunks; unsigned char *chunks; + unsigned int index; name = &buffer[i]; i += strlen(name) + 1; - assert(i < l); + assert((i+4) < l); + index = buffer[i] | buffer[i+1] << 8 | buffer[i+2] << 16 | buffer[i+3] << 24; + i += 4; nchunks = buffer[i++]; assert(i + nchunks == l); chunks = (unsigned char *)&buffer[i]; - return sc->h_write(name, nchunks, chunks, sc->user); + return sc->h_write(name, index, nchunks, chunks, sc->user); } case MESSAGE_READ: { char *name; + unsigned int index; name = &buffer[i]; i += strlen(name) + 1; - assert(i == l); + assert((i+4) == l); + index = buffer[i] | buffer[i+1] << 8 | buffer[i+2] << 16 | buffer[i+3] << 24; - return sc->h_read(name, sc->user); + return sc->h_read(name, index, sc->user); } default: return 0; diff --git a/vpi/ipc.h b/vpi/ipc.h index ba07ede5..baad5647 100644 --- a/vpi/ipc.h +++ b/vpi/ipc.h @@ -4,8 +4,8 @@ struct ipc_softc; typedef int(*go_handler)(void *); -typedef int(*write_handler)(char *, int, const unsigned char *, void *); -typedef int(*read_handler)(char *, void *); +typedef int(*write_handler)(char *, int, int, const unsigned char *, void *); +typedef int(*read_handler)(char *, int, void *); struct ipc_softc *ipc_connect(const char *sockaddr, go_handler h_go, write_handler h_write, read_handler h_read, void *user); diff --git a/vpi/main.c b/vpi/main.c index 0157df1f..324be66d 100644 --- a/vpi/main.c +++ b/vpi/main.c @@ -23,7 +23,7 @@ static s_vpi_time zero_delay = { .low = 0 }; -static int h_write(char *name, int nchunks, const unsigned char *chunks, void *user) +static int h_write(char *name, int index, int nchunks, const unsigned char *chunks, void *user) { vpiHandle item; s_vpi_vecval vector[64]; @@ -35,6 +35,10 @@ static int h_write(char *name, int nchunks, const unsigned char *chunks, void *u fprintf(stderr, "Attempted to write non-existing signal %s\n", name); return 0; } + if(vpi_get(vpiType, item) == vpiMemory) + item = vpi_handle_by_index(item, index); + else + assert(index == 0); assert(nchunks <= 255); for(i=0;i<64;i++) { @@ -51,7 +55,7 @@ static int h_write(char *name, int nchunks, const unsigned char *chunks, void *u return 1; } -static int h_read(char *name, void *user) +static int h_read(char *name, int index, void *user) { struct migensim_softc *sc = (struct migensim_softc *)user; vpiHandle item; @@ -68,6 +72,10 @@ static int h_read(char *name, void *user) fprintf(stderr, "Attempted to read non-existing signal %s\n", name); return 0; } + if(vpi_get(vpiType, item) == vpiMemory) + item = vpi_handle_by_index(item, index); + else + assert(index == 0); value.format = vpiVectorVal; vpi_get_value(item, &value); -- 2.30.2