lasmibus/Crossbar: more flexible master assignment
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sat, 23 Nov 2013 16:51:22 +0000 (17:51 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sat, 23 Nov 2013 16:51:22 +0000 (17:51 +0100)
migen/bus/lasmibus.py

index 62f5db0686328d38e85f0bcf5df22b6a8502873f..906fd2caa435dc302c7839e9de2d032542cb16d8 100644 (file)
@@ -41,39 +41,51 @@ def _getattr_all(l, attr):
        return r
 
 class Crossbar(Module):
-       def __init__(self, controllers, nmasters, cba_shift):
-               ncontrollers = len(controllers)
-               rca_bits = _getattr_all(controllers, "aw")
-               dw = _getattr_all(controllers, "dw")
-               nbanks = _getattr_all(controllers, "nbanks")
-               req_queue_size = _getattr_all(controllers, "req_queue_size")
-               read_latency = _getattr_all(controllers, "read_latency")
-               write_latency = _getattr_all(controllers, "write_latency")
+       def __init__(self, controllers, cba_shift):
+               self._controllers = controllers
+               self._cba_shift = cba_shift
 
-               bank_bits = log2_int(nbanks, False)
-               controller_bits = log2_int(ncontrollers, False)
-               self.masters = [Interface(rca_bits + bank_bits + controller_bits, dw, 1, req_queue_size, read_latency, write_latency)
-                       for i in range(nmasters)]
+               self._rca_bits = _getattr_all(controllers, "aw")
+               self._dw = _getattr_all(controllers, "dw")
+               self._nbanks = _getattr_all(controllers, "nbanks")
+               self._req_queue_size = _getattr_all(controllers, "req_queue_size")
+               self._read_latency = _getattr_all(controllers, "read_latency")
+               self._write_latency = _getattr_all(controllers, "write_latency")
 
-               ###
+               self._bank_bits = log2_int(self._nbanks, False)
+               self._controller_bits = log2_int(len(self._controllers), False)
 
-               m_ca, m_ba, m_rca = self._split_master_addresses(controller_bits, bank_bits, rca_bits, cba_shift)
+               self._masters = []
+
+       def get_master(self):
+               if self.finalized:
+                       raise FinalizeError
+               lasmi_master = Interface(self._rca_bits + self._bank_bits + self._controller_bits,
+                       self._dw, 1, self._req_queue_size, self._read_latency, self._write_latency)
+               self._masters.append(lasmi_master)
+               return lasmi_master
+
+       def do_finalize(self):
+               nmasters = len(self._masters)
+
+               m_ca, m_ba, m_rca = self._split_master_addresses(self._controller_bits,
+                       self._bank_bits, self._rca_bits, self._cba_shift)
                
-               for nc, controller in enumerate(controllers):
-                       if controller_bits:
+               for nc, controller in enumerate(self._controllers):
+                       if self._controller_bits:
                                controller_selected = [ca == nc for ca in m_ca]
                        else:
                                controller_selected = [1]*nmasters
                        master_req_acks = [0]*nmasters
                        master_dat_acks = [0]*nmasters
-                       rrs = [roundrobin.RoundRobin(nmasters, roundrobin.SP_CE) for n in range(nbanks)]
+                       rrs = [roundrobin.RoundRobin(nmasters, roundrobin.SP_CE) for n in range(self._nbanks)]
                        self.submodules += rrs
                        for nb, rr in enumerate(rrs):
                                bank = getattr(controller, "bank"+str(nb))
 
                                # for each master, determine if another bank locks it
                                master_locked = []
-                               for nm, master in enumerate(self.masters):
+                               for nm, master in enumerate(self._masters):
                                        locked = 0
                                        for other_nb, other_rr in enumerate(rrs):
                                                if other_nb != nb:
@@ -83,7 +95,7 @@ class Crossbar(Module):
 
                                # arbitrate
                                bank_selected = [cs & (ba == nb) & ~locked for cs, ba, locked in zip(controller_selected, m_ba, master_locked)]
-                               bank_requested = [bs & master.stb for bs, master in zip(bank_selected, self.masters)]
+                               bank_requested = [bs & master.stb for bs, master in zip(bank_selected, self._masters)]
                                self.comb += [
                                        rr.request.eq(Cat(*bank_requested)),
                                        rr.ce.eq(~bank.stb & ~bank.lock)
@@ -92,7 +104,7 @@ class Crossbar(Module):
                                # route requests
                                self.comb += [
                                        bank.adr.eq(Array(m_rca)[rr.grant]),
-                                       bank.we.eq(Array(self.masters)[rr.grant].we),
+                                       bank.we.eq(Array(self._masters)[rr.grant].we),
                                        bank.stb.eq(Array(bank_requested)[rr.grant])
                                ]
                                master_req_acks = [master_req_ack | ((rr.grant == nm) & bank_selected[nm] & bank.req_ack)
@@ -100,20 +112,20 @@ class Crossbar(Module):
                                master_dat_acks = [master_dat_ack | ((rr.grant == nm) & bank.dat_ack)
                                        for nm, master_dat_ack in enumerate(master_dat_acks)]
 
-                       self.comb += [master.req_ack.eq(master_req_ack) for master, master_req_ack in zip(self.masters, master_req_acks)]
-                       self.comb += [master.dat_ack.eq(master_dat_ack) for master, master_dat_ack in zip(self.masters, master_dat_acks)]
+                       self.comb += [master.req_ack.eq(master_req_ack) for master, master_req_ack in zip(self._masters, master_req_acks)]
+                       self.comb += [master.dat_ack.eq(master_dat_ack) for master, master_dat_ack in zip(self._masters, master_dat_acks)]
 
                        # route data writes
                        controller_selected_wl = controller_selected
-                       for i in range(write_latency):
+                       for i in range(self._write_latency):
                                n_controller_selected_wl = [Signal() for i in range(nmasters)]
                                self.sync += [n.eq(o) for n, o in zip(n_controller_selected_wl, controller_selected_wl)]
                                controller_selected_wl = n_controller_selected_wl
                        dat_w_maskselect = []
                        dat_we_maskselect = []
-                       for master, selected in zip(self.masters, controller_selected_wl):
-                               o_dat_w = Signal(dw)
-                               o_dat_we = Signal(dw//8)
+                       for master, selected in zip(self._masters, controller_selected_wl):
+                               o_dat_w = Signal(self._dw)
+                               o_dat_we = Signal(self._dw//8)
                                self.comb += If(selected,
                                                o_dat_w.eq(master.dat_w),
                                                o_dat_we.eq(master.dat_we)
@@ -126,31 +138,31 @@ class Crossbar(Module):
                        ]
 
                # route data reads
-               if controller_bits:
-                       for master in self.masters:
-                               controller_sel = Signal(controller_bits)
-                               for nc, controller in enumerate(controllers):
+               if self._controller_bits:
+                       for master in self._masters:
+                               controller_sel = Signal(self._controller_bits)
+                               for nc, controller in enumerate(self._controllers):
                                        for nb in range(nbanks):
                                                bank = getattr(controller, "bank"+str(nb))
                                                self.comb += If(bank.stb & bank.ack, controller_sel.eq(nc))
-                               for i in range(read_latency):
-                                       n_controller_sel = Signal(controller_bits)
+                               for i in range(self._read_latency):
+                                       n_controller_sel = Signal(self._controller_bits)
                                        self.sync += n_controller_sel.eq(controller_sel)
                                        controller_sel = n_controller_sel
-                               self.comb += master.dat_r.eq(Array(controllers)[controller_sel].dat_r)
+                               self.comb += master.dat_r.eq(Array(self._controllers)[controller_sel].dat_r)
                else:
-                       self.comb += [master.dat_r.eq(controllers[0].dat_r) for master in self.masters]
+                       self.comb += [master.dat_r.eq(self._controllers[0].dat_r) for master in self._masters]
 
        def _split_master_addresses(self, controller_bits, bank_bits, rca_bits, cba_shift):
                m_ca = []       # controller address
                m_ba = []       # bank address
                m_rca = []      # row and column address
-               for master in self.masters:
-                       cba = Signal(controller_bits + bank_bits)
-                       rca = Signal(rca_bits)
+               for master in self._masters:
+                       cba = Signal(self._controller_bits + self._bank_bits)
+                       rca = Signal(self._rca_bits)
                        cba_upper = cba_shift + controller_bits + bank_bits
                        self.comb += cba.eq(master.adr[cba_shift:cba_upper])
-                       if cba_shift < rca_bits:
+                       if cba_shift < self._rca_bits:
                                if cba_shift:
                                        self.comb += rca.eq(Cat(master.adr[:cba_shift], master.adr[cba_upper:]))
                                else:
@@ -158,9 +170,9 @@ class Crossbar(Module):
                        else:
                                self.comb += rca.eq(master.adr[:cba_shift])
 
-                       if controller_bits:
-                               ca = Signal(controller_bits)
-                               ba = Signal(bank_bits)
+                       if self._controller_bits:
+                               ca = Signal(self._controller_bits)
+                               ba = Signal(self._bank_bits)
                                self.comb += Cat(ba, ca).eq(cba)
                        else:
                                ca = None