From 792b8fed1bfd78cc228cec85ec4c4acc59aee180 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 12 May 2013 15:58:39 +0200 Subject: [PATCH] bus/asmi: port sharing support --- migen/bus/asmibus.py | 81 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/migen/bus/asmibus.py b/migen/bus/asmibus.py index 46e76bc2d..535acc32c 100644 --- a/migen/bus/asmibus.py +++ b/migen/bus/asmibus.py @@ -1,6 +1,7 @@ from migen.fhdl.structure import * from migen.fhdl.module import Module, FinalizeError from migen.genlib.misc import optree +from migen.genlib import roundrobin from migen.bus.transactions import * from migen.sim.generic import Proxy @@ -300,3 +301,83 @@ class Target(Module): else: s.wr(self.hub.call, 0) 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)) + ]