bus/asmi: port sharing support
This commit is contained in:
parent
f202946717
commit
792b8fed1b
|
@ -1,6 +1,7 @@
|
||||||
from migen.fhdl.structure import *
|
from migen.fhdl.structure import *
|
||||||
from migen.fhdl.module import Module, FinalizeError
|
from migen.fhdl.module import Module, FinalizeError
|
||||||
from migen.genlib.misc import optree
|
from migen.genlib.misc import optree
|
||||||
|
from migen.genlib import roundrobin
|
||||||
from migen.bus.transactions import *
|
from migen.bus.transactions import *
|
||||||
from migen.sim.generic import Proxy
|
from migen.sim.generic import Proxy
|
||||||
|
|
||||||
|
@ -300,3 +301,83 @@ class Target(Module):
|
||||||
else:
|
else:
|
||||||
s.wr(self.hub.call, 0)
|
s.wr(self.hub.call, 0)
|
||||||
self._calling_tag = -1
|
self._calling_tag = -1
|
||||||
|
|
||||||
|
# Port sharing
|
||||||
|
|
||||||
|
class SharedPort:
|
||||||
|
def __init__(self, base_port):
|
||||||
|
if not base_port.finalized:
|
||||||
|
raise FinalizeError
|
||||||
|
self.finalized = True
|
||||||
|
|
||||||
|
nslots = len(base_port.slots)
|
||||||
|
|
||||||
|
self.hub = base_port.hub
|
||||||
|
self.base = base_port.base
|
||||||
|
# 1 if that slot is assigned to us
|
||||||
|
self.slots = [Signal() for i in range(nslots)]
|
||||||
|
|
||||||
|
# request issuance
|
||||||
|
self.adr = Signal(self.hub.aw)
|
||||||
|
self.we = Signal()
|
||||||
|
self.stb = Signal()
|
||||||
|
if nslots > 1:
|
||||||
|
self.tag_issue = Signal(max=nslots)
|
||||||
|
self.ack = Signal()
|
||||||
|
|
||||||
|
# request completion
|
||||||
|
self.call = Signal()
|
||||||
|
self.tag_call = Signal(self.hub.tagbits)
|
||||||
|
self.dat_r = Signal(self.hub.dw)
|
||||||
|
self.dat_w = Signal(self.hub.dw)
|
||||||
|
self.dat_wm = Signal(self.hub.dw//8)
|
||||||
|
|
||||||
|
def get_call_expression(self, slotn=0):
|
||||||
|
if not self.finalized:
|
||||||
|
raise FinalizeError
|
||||||
|
return self.call \
|
||||||
|
& (self.tag_call == (self.base + slotn))
|
||||||
|
|
||||||
|
class PortSharer(Module):
|
||||||
|
def __init__(self, base_port, nshares):
|
||||||
|
self.shared_ports = [SharedPort(base_port) for i in range(nshares)]
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
# request issuance
|
||||||
|
self.submodules.rr = roundrobin.RoundRobin(nshares, roundrobin.SP_CE)
|
||||||
|
self.comb += [
|
||||||
|
self.rr.request.eq(Cat(*[sp.stb for sp in self.shared_ports])),
|
||||||
|
self.rr.ce.eq(base_port.ack)
|
||||||
|
]
|
||||||
|
self.comb += [
|
||||||
|
base_port.adr.eq(Array(sp.adr for sp in self.shared_ports)[self.rr.grant]),
|
||||||
|
base_port.we.eq(Array(sp.we for sp in self.shared_ports)[self.rr.grant]),
|
||||||
|
base_port.stb.eq(Array(sp.stb for sp in self.shared_ports)[self.rr.grant]),
|
||||||
|
]
|
||||||
|
if hasattr(base_port, "tag_issue"):
|
||||||
|
self.comb += [sp.tag_issue.eq(base_port.tag_issue) for sp in self.shared_ports]
|
||||||
|
self.comb += [sp.ack.eq(base_port.ack & (self.rr.grant == n)) for n, sp in enumerate(self.shared_ports)]
|
||||||
|
|
||||||
|
# request completion
|
||||||
|
self.comb += [sp.call.eq(base_port.call & Array(sp.slots)[base_port.tag_call-base_port.base])
|
||||||
|
for sp in self.shared_ports]
|
||||||
|
self.comb += [sp.tag_call.eq(base_port.tag_call) for sp in self.shared_ports]
|
||||||
|
self.comb += [sp.dat_r.eq(base_port.dat_r) for sp in self.shared_ports]
|
||||||
|
self.comb += [
|
||||||
|
base_port.dat_w.eq(optree("|", [sp.dat_w for sp in self.shared_ports])),
|
||||||
|
base_port.dat_wm.eq(optree("|", [sp.dat_wm for sp in self.shared_ports])),
|
||||||
|
]
|
||||||
|
|
||||||
|
# request ownership tracking
|
||||||
|
if hasattr(base_port, "tag_issue"):
|
||||||
|
for sp in self.shared_ports:
|
||||||
|
self.sync += If(sp.stb & sp.ack, Array(sp.slots)[sp.tag_issue].eq(1))
|
||||||
|
for n, slot in enumerate(sp.slots):
|
||||||
|
self.sync += If(base_port.call & (base_port.tag_call == (base_port.base + n)), slot.eq(0))
|
||||||
|
else:
|
||||||
|
for sp in self.shared_ports:
|
||||||
|
self.sync += [
|
||||||
|
If(sp.stb & sp.ack, sp.slots[0].eq(1)),
|
||||||
|
If(base_port.call & (base_port.tag_call == base_port.base), sp.slots[0].eq(0))
|
||||||
|
]
|
||||||
|
|
Loading…
Reference in New Issue