Skip to content

Commit

Permalink
sim: memory access
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastien Bourdeauducq committed Mar 6, 2012
1 parent db8f8bf commit 8160ced
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 32 deletions.
6 changes: 3 additions & 3 deletions examples/basic_sim.py
Expand Up @@ -7,12 +7,12 @@ def __init__(self):
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))]
Expand Down
27 changes: 27 additions & 0 deletions 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()
4 changes: 2 additions & 2 deletions migen/fhdl/structure.py
Expand Up @@ -276,6 +276,6 @@ def __add__(self, other):
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)
40 changes: 25 additions & 15 deletions migen/sim/generic.py
Expand Up @@ -84,44 +84,54 @@ def __init__(self, fragment, sim_runner, top_level=None, sockaddr="simsocket"):
rst_signal=rst_signal,
return_ns=True)

self.cycle_counter = 0
self.cycle_counter = -1
self.interrupt = False

self.sim_runner = sim_runner
self.sim_runner.start(c_top, c_fragment)
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))
24 changes: 20 additions & 4 deletions migen/sim/ipc.py
Expand Up @@ -5,6 +5,9 @@
# Message classes
#

class Int32(int):
pass

class Message:
def __init__(self, *pvalues):
for parameter, value in zip(self.parameters, pvalues):
Expand All @@ -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
Expand All @@ -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:
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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)
Expand Down
13 changes: 9 additions & 4 deletions vpi/ipc.c
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions vpi/ipc.h
Expand Up @@ -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);
Expand Down
12 changes: 10 additions & 2 deletions vpi/main.c
Expand Up @@ -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];
Expand All @@ -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++) {
Expand All @@ -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;
Expand All @@ -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);
Expand Down

0 comments on commit 8160ced

Please sign in to comment.