sim: memory access

This commit is contained in:
Sebastien Bourdeauducq 2012-03-06 19:29:39 +01:00
parent db8f8bf2e3
commit 8160ced2e9
8 changed files with 98 additions and 32 deletions

View 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))]

27
examples/memory_sim.py Normal file
View file

@ -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()

View 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)

View 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))

View 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)

View file

@ -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;

View file

@ -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);

View 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);