sim: memory access
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Tue, 6 Mar 2012 18:29:39 +0000 (19:29 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Tue, 6 Mar 2012 18:29:39 +0000 (19:29 +0100)
examples/basic_sim.py
examples/memory_sim.py [new file with mode: 0644]
migen/fhdl/structure.py
migen/sim/generic.py
migen/sim/ipc.py
vpi/ipc.c
vpi/ipc.h
vpi/main.c

index 3578bc977af463a05b1fff7a7c5491b0ca5b90b6..a4f17c465cd292018bc83c68a33e69190d3ba4cb 100644 (file)
@@ -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 (file)
index 0000000..7c58b2b
--- /dev/null
@@ -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()
index 21e5cb0ea309b554f77052463a45594293d3fc2c..e5730ff508349ac02e98a00c7c84141c64fede3f 100644 (file)
@@ -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)
index 60057e1ebf1d1300cc10a350811e4c5d4073d1ab..dddc7e41ced78f94ee8a50f63db01a3079475012 100644 (file)
@@ -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))
index 9464a12c916f1c9f58ac0d6e841e028eadc3c548..ca59c4f793a9b86e5bc593819b3cd1d1c864f8d1 100644 (file)
@@ -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)
index c78fd20ef485818f4d5be74276c414a78aec99f9..c76081d30a5fe72e6107552403bbb1e1436901ea 100644 (file)
--- 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;
index ba07ede5f1686f7b31976a72aab6647e36380cf2..baad56479591bee4dfa8e920429237978dfbc157 100644 (file)
--- 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);
index 0157df1f02b738de4799b0b564c74f5680c7b2f3..324be66da27c770a7b1c216cfd32434e00c2982d 100644 (file)
@@ -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);