Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/migen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 35f9f2e9d7c7
Choose a base ref
...
head repository: m-labs/migen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 9f560cb758e9
Choose a head ref
  • 4 commits
  • 4 files changed
  • 1 contributor

Commits on Jun 9, 2013

  1. examples/sim: rename abstract_transactions to abstract_transactions_w…

    …b, use new APIs, remove ASMI
    Sebastien Bourdeauducq committed Jun 9, 2013
    Copy the full SHA
    2948f6a View commit details
  2. bus/lasmibus: add target and initiator

    Sebastien Bourdeauducq committed Jun 9, 2013
    Copy the full SHA
    a836cba View commit details
  3. bus/lasmibus: bugfixes

    Sebastien Bourdeauducq committed Jun 9, 2013
    Copy the full SHA
    f2e2397 View commit details
  4. examples/sim: add LASMI demo

    Sebastien Bourdeauducq committed Jun 9, 2013
    Copy the full SHA
    9f560cb View commit details
Showing with 244 additions and 115 deletions.
  1. +0 −111 examples/sim/abstract_transactions.py
  2. +40 −0 examples/sim/abstract_transactions_lasmi.py
  3. +89 −0 examples/sim/abstract_transactions_wb.py
  4. +115 −4 migen/bus/lasmibus.py
111 changes: 0 additions & 111 deletions examples/sim/abstract_transactions.py

This file was deleted.

40 changes: 40 additions & 0 deletions examples/sim/abstract_transactions_lasmi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from migen.fhdl.std import *
from migen.bus.transactions import *
from migen.bus import lasmibus
from migen.sim.generic import Simulator

def my_generator(n):
for x in range(4):
t = TWrite(4*n+x, 0x100+x)
yield t
print("Wrote in {0} cycle(s)".format(t.latency))

for x in range(4):
t = TRead(4*n+x)
yield t
print("Read {0:x} in {1:x} cycle(s)".format(t.data, t.latency))

class MyModel(lasmibus.TargetModel):
def read(self, bank, address):
#print("read from bank {0} address {1}".format(bank, address))
return 0x1000*bank + 0x200+address

def write(self, bank, address, data, we):
print("write to bank {0} address {1:x} data {2:x}".format(bank, address, data))

class TB(Module):
def __init__(self):
self.submodules.controller = lasmibus.Target(MyModel(), aw=4, dw=32, nbanks=4, read_latency=4, write_latency=1)
self.submodules.xbar = lasmibus.Crossbar([self.controller.bus], 4, 2)
self.initiators = [lasmibus.Initiator(my_generator(n), bus) for n, bus in enumerate(self.xbar.masters)]
self.submodules += self.initiators

def do_simulation(self, s):
s.interrupt = all(m.done for m in self.initiators)

def main():
tb = TB()
sim = Simulator(tb)
sim.run()

main()
89 changes: 89 additions & 0 deletions examples/sim/abstract_transactions_wb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from random import Random

from migen.fhdl.std import *
from migen.bus.transactions import *
from migen.bus import wishbone
from migen.sim.generic import Simulator

# Our bus master.
# Python generators let us program bus transactions in an elegant sequential style.
def my_generator():
prng = Random(92837)

# Write to the first addresses.
for x in range(10):
t = TWrite(x, 2*x)
yield t
print("Wrote in " + str(t.latency) + " cycle(s)")
# Insert some dead cycles to simulate bus inactivity.
for delay in range(prng.randrange(0, 3)):
yield None

# Read from the first addresses.
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

# Our bus slave.
class MyModelWB(wishbone.TargetModel):
def __init__(self):
self.prng = Random(763627)

def read(self, address):
return address + 4

def can_ack(self, bus):
# Simulate variable latency.
return self.prng.randrange(0, 2)

class TB(Module):
def __init__(self):
# The "wishbone.Initiator" library component runs our generator
# and manipulates the bus signals accordingly.
self.submodules.master = wishbone.Initiator(my_generator())
# The "wishbone.Target" library component examines the bus signals
# and calls into our model object.
self.submodules.slave = wishbone.Target(MyModelWB())
# The "wishbone.Tap" library component examines the bus at the slave port
# and displays the transactions on the console (<TRead...>/<TWrite...>).
self.submodules.tap = wishbone.Tap(self.slave.bus)
# Connect the master to the slave.
self.submodules.intercon = wishbone.InterconnectPointToPoint(self.master.bus, self.slave.bus)

def do_simulation(self, s):
# Terminate the simulation when the initiator is done (i.e. our generator is exhausted).
s.interrupt = self.master.done

def main():
tb = TB()
sim = Simulator(tb)
sim.run()

main()

# Output:
# <TWrite adr:0x0 dat:0x0>
# Wrote in 0 cycle(s)
# <TWrite adr:0x1 dat:0x2>
# Wrote in 0 cycle(s)
# <TWrite adr:0x2 dat:0x4>
# Wrote in 0 cycle(s)
# <TWrite adr:0x3 dat:0x6>
# Wrote in 1 cycle(s)
# <TWrite adr:0x4 dat:0x8>
# Wrote in 1 cycle(s)
# <TWrite adr:0x5 dat:0xa>
# Wrote in 2 cycle(s)
# ...
# <TRead adr:0x0 dat:0x4>
# Read 4 in 2 cycle(s)
# <TRead adr:0x1 dat:0x5>
# Read 5 in 2 cycle(s)
# <TRead adr:0x2 dat:0x6>
# Read 6 in 1 cycle(s)
# <TRead adr:0x3 dat:0x7>
# Read 7 in 1 cycle(s)
# ...
119 changes: 115 additions & 4 deletions migen/bus/lasmibus.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from migen.fhdl.std import *
from migen.bus.transactions import *
from migen.genlib import roundrobin
from migen.genlib.record import *
from migen.genlib.misc import optree
@@ -49,7 +50,6 @@ def __init__(self, controllers, nmasters, cba_shift):
controller_bits = log2_int(ncontrollers, False)
self.masters = [Interface(rca_bits + bank_bits + controller_bits, dw, 1, read_latency, write_latency)
for i in range(nmasters)]
masters_a = Array(self.masters)

###

@@ -60,6 +60,7 @@ def __init__(self, controllers, nmasters, cba_shift):
controller_selected = [ca == nc for ca in m_ca]
else:
controller_selected = [1]*nmasters
master_acks = [0]*nmasters
for nb in range(nbanks):
bank = getattr(controller, "bank"+str(nb))

@@ -76,10 +77,13 @@ def __init__(self, controllers, nmasters, cba_shift):
# route requests
self.comb += [
bank.adr.eq(Array(m_rca)[rr.grant]),
bank.we.eq(masters_a[rr.grant].we),
bank.stb.eq(masters_a[rr.grant].stb),
masters_a[rr.grant].ack.eq(bank.ack)
bank.we.eq(Array(self.masters)[rr.grant].we),
bank.stb.eq(Array(bank_requested)[rr.grant])
]
master_acks = [master_ack | ((rr.grant == nm) & bank.ack)
for nm, master_ack in enumerate(master_acks)]

self.comb += [master.ack.eq(master_ack) for master, master_ack in zip(self.masters, master_acks)]

# route data writes
controller_selected_wl = controller_selected
@@ -145,3 +149,110 @@ def _split_master_addresses(self, controller_bits, bank_bits, rca_bits, cba_shif
m_ba.append(ba)
m_rca.append(rca)
return m_ca, m_ba, m_rca

class Initiator(Module):
def __init__(self, generator, bus):
self.generator = generator
self.bus = bus
self.transaction_start = 0
self.transaction = None
self.transaction_end = None
self.done = False

def do_simulation(self, s):
s.wr(self.bus.dat_w, 0)
s.wr(self.bus.dat_we, 0)
if not self.done:
if self.transaction is not None and s.rd(self.bus.ack):
s.wr(self.bus.stb, 0)
if isinstance(self.transaction, TRead):
self.transaction_end = s.cycle_counter + self.bus.read_latency
else:
self.transaction_end = s.cycle_counter + self.bus.write_latency - 1

if self.transaction is None or s.cycle_counter == self.transaction_end:
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)
else:
s.wr(self.bus.dat_w, self.transaction.data)
s.wr(self.bus.dat_we, self.transaction.sel)
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.stb, 1)
s.wr(self.bus.adr, self.transaction.address)
if isinstance(self.transaction, TRead):
s.wr(self.bus.we, 0)
else:
s.wr(self.bus.we, 1)

class TargetModel:
def __init__(self):
self.last_bank = 0

def read(self, bank, address):
return 0

def write(self, bank, address, data, we):
pass

# Round-robin scheduling
def select_bank(self, pending_banks):
if not pending_banks:
return -1
self.last_bank += 1
if self.last_bank > max(pending_banks):
self.last_bank = 0
while self.last_bank not in pending_banks:
self.last_bank += 1
return self.last_bank

class Target(Module):
def __init__(self, model, *ifargs, **ifkwargs):
self.model = model
self.bus = Interface(*ifargs, **ifkwargs)
self.rd_pipeline = [None]*self.bus.read_latency
self.wr_pipeline = [None]*(self.bus.write_latency + 1)

def do_simulation(self, s):
# determine banks with pending requests
pending_banks = set()
for nb in range(self.bus.nbanks):
bank = getattr(self.bus, "bank"+str(nb))
if s.rd(bank.stb) and not s.rd(bank.ack):
pending_banks.add(nb)

# issue new transactions
selected_bank_n = self.model.select_bank(pending_banks)
for nb in range(self.bus.nbanks):
bank = getattr(self.bus, "bank"+str(nb))
if nb == selected_bank_n:
s.wr(bank.ack, 1)
else:
s.wr(bank.ack, 0)

rd_transaction = None
wr_transaction = None
if selected_bank_n >= 0:
selected_bank = getattr(self.bus, "bank"+str(selected_bank_n))
if s.rd(selected_bank.we):
wr_transaction = selected_bank_n, s.rd(selected_bank.adr)
else:
rd_transaction = selected_bank_n, s.rd(selected_bank.adr)

# data pipeline
self.rd_pipeline.append(rd_transaction)
self.wr_pipeline.append(wr_transaction)
done_rd_transaction = self.rd_pipeline.pop(0)
done_wr_transaction = self.wr_pipeline.pop(0)
if done_rd_transaction is not None:
s.wr(self.bus.dat_r, self.model.read(done_rd_transaction[0], done_rd_transaction[1]))
if done_wr_transaction is not None:
self.model.write(done_wr_transaction[0], done_wr_transaction[1],
s.rd(self.bus.dat_w), s.rd(self.bus.dat_we))