Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 3 commits
  • 5 files changed
  • 0 commit comments
  • 1 contributor
View
3  .gitignore
@@ -1,2 +1,5 @@
__pycache__
*.pyc
+vpi/*.o
+vpi/migensim.vpi
+examples/*.vcd
View
53 examples/wb_initiator.py
@@ -0,0 +1,53 @@
+from random import Random
+
+from migen.fhdl.structure import *
+from migen.fhdl import autofragment
+from migen.bus.transactions import *
+from migen.bus import wishbone
+from migen.sim.generic import Simulator
+from migen.sim.icarus import Runner
+
+def my_generator():
+ prng = Random(92837)
+ for x in range(10):
+ t = TWrite(x, 2*x)
+ yield t
+ print("Wrote in " + str(t.latency) + " cycle(s)")
+ for delay in range(prng.randrange(0, 3)):
+ yield None
+ for x in range(10):
+ t = TRead(x)
+ yield t
+ print("Read " + str(t.data) + " in " + str(t.latency) + " cycle(s)")
+ for delay in range(prng.randrange(0, 3)):
+ yield None
+
+class MyPeripheral:
+ def __init__(self):
+ self.bus = wishbone.Interface()
+ self.ack_en = Signal()
+ self.prng = Random(763627)
+
+ def do_simulation(self, s):
+ # Only authorize acks on certain cycles to simulate variable latency
+ s.wr(self.ack_en, self.prng.randrange(0, 2))
+
+ def get_fragment(self):
+ comb = [
+ self.bus.ack.eq(self.bus.cyc & self.bus.stb & self.ack_en),
+ self.bus.dat_r.eq(self.bus.adr + 4)
+ ]
+ return Fragment(comb, sim=[self.do_simulation])
+
+def main():
+ master = wishbone.Initiator(my_generator())
+ slave = MyPeripheral()
+ tap = wishbone.Tap(slave.bus)
+ intercon = wishbone.InterconnectPointToPoint(master.bus, slave.bus)
+ def end_simulation(s):
+ s.interrupt = master.done
+ fragment = autofragment.from_local() + Fragment(sim=[end_simulation])
+ sim = Simulator(fragment, Runner())
+ sim.run()
+
+main()
View
20 migen/bus/transactions.py
@@ -0,0 +1,20 @@
+from migen.fhdl.structure import bits_for
+
+class Transaction:
+ def __init__(self, address, data=0, sel=None):
+ self.address = address
+ self.data = data
+ if sel is None:
+ bytes = (bits_for(data) + 7)//8
+ sel = 2**bytes - 1
+ self.sel = sel
+ self.latency = 0
+
+ def __str__(self):
+ return "<" + self.__class__.__name__ + " adr:" + hex(self.address) + " dat:" + hex(self.data) + ">"
+
+class TRead(Transaction):
+ pass
+
+class TWrite(Transaction):
+ pass
View
76 migen/bus/wishbone.py
@@ -2,6 +2,7 @@
from migen.corelogic import roundrobin
from migen.corelogic.misc import multimux, optree
from migen.bus.simple import *
+from migen.bus.transactions import *
_desc = Description(
(M_TO_S, "adr", 30),
@@ -127,3 +128,78 @@ def __init__(self, masters, slaves, offset=0, register=False):
def get_fragment(self):
return self._arbiter.get_fragment() + self._decoder.get_fragment()
+
+class Tap:
+ def __init__(self, bus=None, handler=print):
+ # If bus is None, create one and act as a normal slave.
+ # If we pass an existing one, dump the transactions
+ # without interfering with the bus.
+ if bus is None:
+ self.bus = Interface()
+ self.ack = True
+ else:
+ self.bus = bus
+ self.ack = False
+ self.handler = handler
+
+ def do_simulation(self, s):
+ if s.rd(self.bus.ack):
+ assert(s.rd(self.bus.cyc) and s.rd(self.bus.stb))
+ if s.rd(self.bus.we):
+ transaction = TWrite(s.rd(self.bus.adr),
+ s.rd(self.bus.dat_w),
+ s.rd(self.bus.sel))
+ else:
+ transaction = TRead(s.rd(self.bus.adr),
+ s.rd(self.bus.dat_r))
+ self.handler(transaction)
+
+ def get_fragment(self):
+ if self.ack:
+ sync = [
+ self.bus.ack.eq(0),
+ If(self.bus.cyc & self.bus.stb & ~self.bus.ack,
+ self.bus.ack.eq(1)
+ )
+ ]
+ else:
+ sync = []
+ return Fragment(sync=sync, sim=[self.do_simulation])
+
+class Initiator:
+ def __init__(self, generator):
+ self.generator = generator
+ self.bus = Interface()
+ self.transaction_start = 0
+ self.transaction = None
+ self.done = False
+
+ def do_simulation(self, s):
+ if not self.done:
+ if self.transaction is None or s.rd(self.bus.ack):
+ if self.transaction is not None:
+ self.transaction.latency = s.cycle_counter - self.transaction_start - 1
+ if isinstance(self.transaction, TRead):
+ self.transaction.data = s.rd(self.bus.dat_r)
+ try:
+ self.transaction = next(self.generator)
+ except StopIteration:
+ self.done = True
+ self.transaction = None
+ if self.transaction is not None:
+ self.transaction_start = s.cycle_counter
+ s.wr(self.bus.cyc, 1)
+ s.wr(self.bus.stb, 1)
+ s.wr(self.bus.adr, self.transaction.address)
+ if isinstance(self.transaction, TWrite):
+ s.wr(self.bus.we, 1)
+ s.wr(self.bus.sel, self.transaction.sel)
+ s.wr(self.bus.dat_w, self.transaction.data)
+ else:
+ s.wr(self.bus.we, 0)
+ else:
+ s.wr(self.bus.cyc, 0)
+ s.wr(self.bus.stb, 0)
+
+ def get_fragment(self):
+ return Fragment(sim=[self.do_simulation])
View
3  vpi/Makefile
@@ -1,12 +1,13 @@
CC=clang
INSTDIR=/usr/lib/ivl
+INCDIRS=
OBJ=ipc.o main.o
all: migensim.vpi
%.o: %.c
- $(CC) -fPIC -Wall -O2 -c -o $@ $<
+ $(CC) -fPIC -Wall -O2 -c $(INCDIRS) -o $@ $<
migensim.vpi: $(OBJ)
$(CC) -shared -o $@ $(OBJ) -lvpi

No commit comments for this range

Something went wrong with that request. Please try again.