bus: simplify and cleanup
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Wed, 15 Feb 2012 15:30:16 +0000 (16:30 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Wed, 15 Feb 2012 15:30:16 +0000 (16:30 +0100)
Unify slave and master interfaces
Remove signal direction suffixes
Generic simple interconnect
Wishbone point-to-point interconnect
Description filter (get_name)
Misc cleanups

examples/wb_intercon/intercon_conv.py
examples/wb_intercon/tb_intercon.v
migen/bus/csr.py
migen/bus/simple.py
migen/bus/wishbone.py
migen/bus/wishbone2asmi.py
migen/bus/wishbone2csr.py

index 277bf82d997cd3159b9f6297881271f4198aaf4c..667d75c2bea59eee320ddfd0f05ab292bea8b15b 100644 (file)
@@ -1,10 +1,10 @@
 from migen.fhdl import verilog
 from migen.bus import wishbone
 
-m1 = wishbone.Master()
-m2 = wishbone.Master()
-s1 = wishbone.Slave()
-s2 = wishbone.Slave()
+m1 = wishbone.Interface()
+m2 = wishbone.Interface()
+s1 = wishbone.Interface()
+s2 = wishbone.Interface()
 wishbonecon0 = wishbone.InterconnectShared(
                [m1, m2],
                [(0, s1), (1, s2)],
@@ -12,8 +12,8 @@ wishbonecon0 = wishbone.InterconnectShared(
                offset=1)
 
 frag = wishbonecon0.get_fragment()
-v = verilog.convert(frag, name="intercon", ios={m1.cyc_o, m1.stb_o, m1.we_o, m1.adr_o, m1.sel_o, m1.dat_o, m1.dat_i, m1.ack_i,
-       m2.cyc_o, m2.stb_o, m2.we_o, m2.adr_o, m2.sel_o, m2.dat_o, m2.dat_i, m2.ack_i,
-       s1.cyc_i, s1.stb_i, s1.we_i, s1.adr_i, s1.sel_i, s1.dat_i, s1.dat_o, s1.ack_o,
-       s2.cyc_i, s2.stb_i, s2.we_i, s2.adr_i, s2.sel_i, s2.dat_i, s2.dat_o, s2.ack_o})
+v = verilog.convert(frag, name="intercon", ios={m1.cyc, m1.stb, m1.we, m1.adr, m1.sel, m1.dat_w, m1.dat_r, m1.ack,
+       m2.cyc, m2.stb, m2.we, m2.adr, m2.sel, m2.dat_r, m2.dat_w, m2.ack,
+       s1.cyc, s1.stb, s1.we, s1.adr, s1.sel, s1.dat_r, s1.dat_w, s1.ack,
+       s2.cyc, s2.stb, s2.we, s2.adr, s2.sel, s2.dat_r, s2.dat_w, s2.ack})
 print(v)
index b424ebad16d6e132a111f6089779b743fea8caa7..30b484d17788b21ba21253e78f995b11726bad2e 100644 (file)
@@ -80,42 +80,42 @@ intercon dut(
        .sys_rst(sys_rst),
 
        // Master 0
-       .m1_wishbone_dat_o(m1_wishbone_dat_w),
-       .m1_wishbone_dat_i(m1_wishbone_dat_r),
-       .m1_wishbone_adr_o(m1_wishbone_adr),
-       .m1_wishbone_we_o(m1_wishbone_we),
-       .m1_wishbone_sel_o(m1_wishbone_sel),
-       .m1_wishbone_cyc_o(m1_wishbone_cyc),
-       .m1_wishbone_stb_o(m1_wishbone_stb),
-       .m1_wishbone_ack_i(m1_wishbone_ack),
+       .m1_wishbone_dat_w(m1_wishbone_dat_w),
+       .m1_wishbone_dat_r(m1_wishbone_dat_r),
+       .m1_wishbone_adr(m1_wishbone_adr),
+       .m1_wishbone_we(m1_wishbone_we),
+       .m1_wishbone_sel(m1_wishbone_sel),
+       .m1_wishbone_cyc(m1_wishbone_cyc),
+       .m1_wishbone_stb(m1_wishbone_stb),
+       .m1_wishbone_ack(m1_wishbone_ack),
        // Master 1
-       .m2_wishbone_dat_o(m2_wishbone_dat_w),
-       .m2_wishbone_dat_i(m2_wishbone_dat_r),
-       .m2_wishbone_adr_o(m2_wishbone_adr),
-       .m2_wishbone_we_o(m2_wishbone_we),
-       .m2_wishbone_sel_o(m2_wishbone_sel),
-       .m2_wishbone_cyc_o(m2_wishbone_cyc),
-       .m2_wishbone_stb_o(m2_wishbone_stb),
-       .m2_wishbone_ack_i(m2_wishbone_ack),
+       .m2_wishbone_dat_w(m2_wishbone_dat_w),
+       .m2_wishbone_dat_r(m2_wishbone_dat_r),
+       .m2_wishbone_adr(m2_wishbone_adr),
+       .m2_wishbone_we(m2_wishbone_we),
+       .m2_wishbone_sel(m2_wishbone_sel),
+       .m2_wishbone_cyc(m2_wishbone_cyc),
+       .m2_wishbone_stb(m2_wishbone_stb),
+       .m2_wishbone_ack(m2_wishbone_ack),
 
        // Slave 0
-       .s1_wishbone_dat_o(s1_wishbone_dat_r),
-       .s1_wishbone_dat_i(s1_wishbone_dat_w),
-       .s1_wishbone_adr_i(s1_wishbone_adr),
-       .s1_wishbone_sel_i(s1_wishbone_sel),
-       .s1_wishbone_we_i(s1_wishbone_we),
-       .s1_wishbone_cyc_i(s1_wishbone_cyc),
-       .s1_wishbone_stb_i(s1_wishbone_stb),
-       .s1_wishbone_ack_o(s1_wishbone_ack),
+       .s1_wishbone_dat_r(s1_wishbone_dat_r),
+       .s1_wishbone_dat_w(s1_wishbone_dat_w),
+       .s1_wishbone_adr(s1_wishbone_adr),
+       .s1_wishbone_sel(s1_wishbone_sel),
+       .s1_wishbone_we(s1_wishbone_we),
+       .s1_wishbone_cyc(s1_wishbone_cyc),
+       .s1_wishbone_stb(s1_wishbone_stb),
+       .s1_wishbone_ack(s1_wishbone_ack),
        // Slave 1
-       .s2_wishbone_dat_o(s2_wishbone_dat_r),
-       .s2_wishbone_dat_i(s2_wishbone_dat_w),
-       .s2_wishbone_adr_i(s2_wishbone_adr),
-       .s2_wishbone_sel_i(s2_wishbone_sel),
-       .s2_wishbone_we_i(s2_wishbone_we),
-       .s2_wishbone_cyc_i(s2_wishbone_cyc),
-       .s2_wishbone_stb_i(s2_wishbone_stb),
-       .s2_wishbone_ack_o(s2_wishbone_ack)
+       .s2_wishbone_dat_r(s2_wishbone_dat_r),
+       .s2_wishbone_dat_w(s2_wishbone_dat_w),
+       .s2_wishbone_adr(s2_wishbone_adr),
+       .s2_wishbone_sel(s2_wishbone_sel),
+       .s2_wishbone_we(s2_wishbone_we),
+       .s2_wishbone_cyc(s2_wishbone_cyc),
+       .s2_wishbone_stb(s2_wishbone_stb),
+       .s2_wishbone_ack(s2_wishbone_ack)
 );
 
 //---------------------------------------------------------------------------
index 9e00932209702e4edaec891e897741b6a34d11f5..9fff20a2de64b05c0dc6c8ee784c3f4f3d393c66 100644 (file)
@@ -1,33 +1,16 @@
 from migen.fhdl.structure import *
-from migen.corelogic.misc import optree
-from migen.bus.simple import Simple
+from migen.bus.simple import *
 
-_desc = [
-       (True,  "adr",  14),
-       (True,  "we",   1),
-       (True,  "dat",  8),
-       (False, "dat",  8)
-]
+_desc = Description(
+       (M_TO_S,        "adr",          14),
+       (M_TO_S,        "we",           1),
+       (M_TO_S,        "dat_w",        8),
+       (S_TO_M,        "dat_r",        8)
+)
 
-class Master(Simple):
+class Interface(SimpleInterface):
        def __init__(self):
-               Simple.__init__(self, _desc, False)
+               SimpleInterface.__init__(self, _desc)
 
-class Slave(Simple):
-       def __init__(self):
-               Simple.__init__(self, _desc, True)
-
-class Interconnect:
-       def __init__(self, master, slaves):
-               self.master = master
-               self.slaves = slaves
-       
-       def get_fragment(self):
-               comb = []
-               for slave in self.slaves:
-                       comb.append(slave.adr_i.eq(self.master.adr_o))
-                       comb.append(slave.we_i.eq(self.master.we_o))
-                       comb.append(slave.dat_i.eq(self.master.dat_o))
-               rb = optree("|", [slave.dat_o for slave in self.slaves])
-               comb.append(self.master.dat_i.eq(rb))
-               return Fragment(comb)
+class Interconnect(SimpleInterconnect):
+       pass
index c4b22177a01caa29150ddce787b04ea0cb7c5817..07c1bb366460fd868eae38065819d1fd4a00027a 100644 (file)
@@ -1,25 +1,44 @@
 from migen.fhdl.structure import *
+from migen.corelogic.misc import optree
 
-def get_sig_name(signal, slave):
-       if signal[0] ^ slave:
-               suffix = "_o"
-       else:
-               suffix = "_i"
-       return signal[1] + suffix
+(S_TO_M, M_TO_S) = range(2)
 
 # desc is a list of tuples, each made up of:
-# 0) boolean: "master to slave"
+# 0) S_TO_M/M_TO_S: data direction
 # 1) string: name
 # 2) int: width
-class Simple():
-       def __init__(self, desc, slave):
-               for signal in desc:
-                       modules = self.__module__.split(".")
-                       busname = modules[len(modules)-1]
-                       signame = get_sig_name(signal, slave)
+
+class Description:
+       def __init__(self, *desc):
+               self.desc = desc
+       
+       def get_names(self, direction, *exclude_list):
+               exclude = set(exclude_list)
+               return [signal[1]
+                       for signal in self.desc
+                       if signal[0] == direction and signal[1] not in exclude]
+
+class SimpleInterface:
+       def __init__(self, desc):
+               self.desc = desc
+               modules = self.__module__.split(".")
+               busname = modules[len(modules)-1]
+               for signal in self.desc.desc:
+                       signame = signal[1]
                        setattr(self, signame, Signal(BV(signal[2]), busname + "_" + signame))
+
+class SimpleInterconnect:
+       def __init__(self, master, slaves):
+               self.master = master
+               self.slaves = slaves
        
-       def signals(self):
-               return [self.__dict__[k]
-                       for k in self.__dict__
-                       if isinstance(self.__dict__[k], Signal)]
+       def get_fragment(self):
+               s2m = master.desc.get_names(S_TO_M)
+               m2s = master.desc.get_names(M_TO_S)
+               comb = [getattr(slave, name).eq(getattr(master, name))
+                       for name in m2s for slave in self.slave]
+               comb += [getattr(master, name).eq(
+                               optree("|", [getattr(slave, name) for slave in self.slaves])
+                       )
+                       for name in s2m]
+               return Fragment(comb)
index fa63fedd6f0d0d0ee594e4ff639ab22432e91606..ee7719b2e11d8dabe57c32be6f37f7bc6721a91f 100644 (file)
@@ -1,29 +1,29 @@
 from migen.fhdl.structure import *
 from migen.corelogic import roundrobin
 from migen.corelogic.misc import multimux, optree
-from migen.bus.simple import Simple, get_sig_name
+from migen.bus.simple import *
 
-_desc = [
-       (True,  "adr",  30),
-       (True,  "dat",  32),
-       (False, "dat",  32),
-       (True,  "sel",  4),
-       (True,  "cyc",  1),
-       (True,  "stb",  1),
-       (False, "ack",  1),
-       (True,  "we",   1),
-       (True,  "cti",  3),
-       (True,  "bte",  2),
-       (False, "err",  1)
-]
+_desc = Description(
+       (M_TO_S,        "adr",          30),
+       (M_TO_S,        "dat_w",        32),
+       (S_TO_M,        "dat_r",        32),
+       (M_TO_S,        "sel",          4),
+       (M_TO_S,        "cyc",          1),
+       (M_TO_S,        "stb",          1),
+       (S_TO_M,        "ack",          1),
+       (M_TO_S,        "we",           1),
+       (M_TO_S,        "cti",          3),
+       (M_TO_S,        "bte",          2),
+       (S_TO_M,        "err",          1)
+)
 
-class Master(Simple):
+class Interface(SimpleInterface):
        def __init__(self):
-               Simple.__init__(self, _desc, False)
+               SimpleInterface.__init__(self, _desc)
 
-class Slave(Simple):
-       def __init__(self):
-               Simple.__init__(self, _desc, True)
+class InterconnectPointToPoint(SimpleInterconnect):
+       def __init__(self, master, slave):
+               SimpleInterconnect.__init__(self, master, [slave])
 
 class Arbiter:
        def __init__(self, masters, target):
@@ -35,26 +35,23 @@ class Arbiter:
                comb = []
                
                # mux master->slave signals
-               m2s_names = [get_sig_name(x, False) for x in _desc if x[0]]
+               m2s_names = _desc.get_names(M_TO_S)
                m2s_masters = [[getattr(m, name) for name in m2s_names] for m in self.masters]
                m2s_target = [getattr(self.target, name) for name in m2s_names]
                comb += multimux(self.rr.grant, m2s_masters, m2s_target)
                
                # connect slave->master signals
-               s2m_names = [get_sig_name(x, False) for x in _desc if not x[0]]
-               for name in s2m_names:
+               for name in _desc.get_names(S_TO_M):
                        source = getattr(self.target, name)
-                       i = 0
-                       for m in self.masters:
+                       for i, m in enumerate(self.masters):
                                dest = getattr(m, name)
-                               if name == "ack_i" or name == "err_i":
+                               if name == "ack" or name == "err":
                                        comb.append(dest.eq(source & (self.rr.grant == Constant(i, self.rr.grant.bv))))
                                else:
                                        comb.append(dest.eq(source))
-                               i += 1
                
                # connect bus requests to round-robin selector
-               reqs = [m.cyc_o for m in self.masters]
+               reqs = [m.cyc for m in self.masters]
                comb.append(self.rr.request.eq(Cat(*reqs)))
                
                return Fragment(comb) + self.rr.get_fragment()
@@ -92,42 +89,38 @@ class Decoder:
                slave_sel_r = Signal(BV(ns))
                
                # decode slave addresses
-               i = 0
-               hi = self.master.adr_o.bv.width - self.offset
-               for addr in self.addresses:
-                       comb.append(slave_sel[i].eq(
-                               self.master.adr_o[hi-addr.bv.width:hi] == addr))
-                       i += 1
+               hi = self.master.adr.bv.width - self.offset
+               comb += [slave_sel[i].eq(self.master.adr[hi-addr.bv.width:hi] == addr)
+                       for i, addr in enumerate(self.addresses)]
                if self.register:
                        sync.append(slave_sel_r.eq(slave_sel))
                else:
                        comb.append(slave_sel_r.eq(slave_sel))
                
                # connect master->slaves signals except cyc
-               m2s_names = [(get_sig_name(x, False), get_sig_name(x, True))
-                       for x in _desc if x[0] and x[1] != "cyc"]
-               comb += [getattr(slave[1], name[1]).eq(getattr(self.master, name[0]))
+               m2s_names = _desc.get_names(M_TO_S, "cyc")
+               comb += [getattr(slave[1], name).eq(getattr(self.master, name))
                        for name in m2s_names for slave in self.slaves]
                
                # combine cyc with slave selection signals
-               i = 0
-               for slave in self.slaves:
-                       comb.append(slave[1].cyc_i.eq(self.master.cyc_o & slave_sel[i]))
-                       i += 1
+               comb += [slave[1].cyc.eq(self.master.cyc & slave_sel[i])
+                       for i, slave in enumerate(self.slaves)]
                
                # generate master ack (resp. err) by ORing all slave acks (resp. errs)
-               comb.append(self.master.ack_i.eq(optree("|", [slave[1].ack_o for slave in self.slaves])))
-               comb.append(self.master.err_i.eq(optree("|", [slave[1].err_o for slave in self.slaves])))
+               comb += [
+                       self.master.ack.eq(optree("|", [slave[1].ack for slave in self.slaves])),
+                       self.master.err.eq(optree("|", [slave[1].err for slave in self.slaves]))
+               ]
                
                # mux (1-hot) slave data return
-               masked = [Replicate(slave_sel_r[i], self.master.dat_i.bv.width) & self.slaves[i][1].dat_o for i in range(len(self.slaves))]
-               comb.append(self.master.dat_i.eq(optree("|", masked)))
+               masked = [Replicate(slave_sel_r[i], self.master.dat_r.bv.width) & self.slaves[i][1].dat_r for i in range(len(self.slaves))]
+               comb.append(self.master.dat_r.eq(optree("|", masked)))
                
                return Fragment(comb, sync)
 
 class InterconnectShared:
        def __init__(self, masters, slaves, offset=0, register=False):
-               self._shared = Master()
+               self._shared = Interface()
                self._arbiter = Arbiter(masters, self._shared)
                self._decoder = Decoder(self._shared, slaves, offset, register)
                self.addresses = self._decoder.addresses
index c7f35043370842f44a6e8d6df7e102f0106a4fec..23544d0d0857755b5c4d9f59393ebde76d96b268 100644 (file)
@@ -18,7 +18,7 @@ def _log2_int(n):
 # cachesize (in 32-bit words) is the size of the data store, must be a power of 2
 class WB2ASMI:
        def __init__(self, cachesize, asmiport):
-               self.wishbone = wishbone.Slave()
+               self.wishbone = wishbone.Interface()
                self.cachesize = cachesize
                self.asmiport = asmiport
                if len(self.asmiport.slots) != 1:
@@ -41,7 +41,7 @@ class WB2ASMI:
                addressbits = aaw + offsetbits
                linebits = _log2_int(self.cachesize) - offsetbits
                tagbits = aaw - linebits
-               adr_offset, adr_line, adr_tag = split(self.wishbone.adr_i, offsetbits, linebits, tagbits)
+               adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits)
                
                # Data memory
                data_adr = Signal(BV(linebits))
@@ -60,16 +60,16 @@ class WB2ASMI:
                                data_di.eq(self.asmiport.dat_r),
                                data_we.eq(Replicate(1, adw//8))
                        ).Else(
-                               data_di.eq(Replicate(self.wishbone.dat_i, adw//32)),
-                               If(self.wishbone.cyc_i & self.wishbone.stb_i & self.wishbone.we_i & self.wishbone.ack_o,
-                                       displacer(self.wishbone.sel_i, adr_offset, data_we, 2**offsetbits, reverse=True)
+                               data_di.eq(Replicate(self.wishbone.dat_w, adw//32)),
+                               If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack,
+                                       displacer(self.wishbone.sel, adr_offset, data_we, 2**offsetbits, reverse=True)
                                )
                        ),
                        If(write_to_asmi,
                                self.asmiport.dat_w.eq(data_do),
                                self.asmiport.dat_wm.eq(Replicate(1, adw//8))
                        ),
-                       chooser(data_do, adr_offset_r, self.wishbone.dat_o, reverse=True)
+                       chooser(data_do, adr_offset_r, self.wishbone.dat_r, reverse=True)
                ]
                sync += [
                        adr_offset_r.eq(adr_offset)
@@ -102,12 +102,12 @@ class WB2ASMI:
                        "REFILL_WRTAG", "REFILL_ISSUE", "REFILL_WAIT", "REFILL_COMPLETE")
                
                fsm.act(fsm.IDLE,
-                       If(self.wishbone.cyc_i & self.wishbone.stb_i, fsm.next_state(fsm.TEST_HIT))
+                       If(self.wishbone.cyc & self.wishbone.stb, fsm.next_state(fsm.TEST_HIT))
                )
                fsm.act(fsm.TEST_HIT,
                        If(tag_do.tag == adr_tag,
-                               self.wishbone.ack_o.eq(1),
-                               If(self.wishbone.we_i,
+                               self.wishbone.ack.eq(1),
+                               If(self.wishbone.we,
                                        tag_di.dirty.eq(1),
                                        tag_we.eq(1)
                                ),
index bd5406eec4cb194432fcdc4988b13b107f44d800..21114b46cc95744e87df6f4ebb7ec632faa30d2a 100644 (file)
@@ -5,18 +5,18 @@ from migen.corelogic import timeline
 
 class WB2CSR:
        def __init__(self):
-               self.wishbone = wishbone.Slave()
-               self.csr = csr.Master()
-               self.timeline = timeline.Timeline(self.wishbone.cyc_i & self.wishbone.stb_i,
-                       [(1, [self.csr.we_o.eq(self.wishbone.we_i)]),
-                       (2, [self.wishbone.ack_o.eq(1)]),
-                       (3, [self.wishbone.ack_o.eq(0)])])
+               self.wishbone = wishbone.Interface()
+               self.csr = csr.Interface()
+               self.timeline = timeline.Timeline(self.wishbone.cyc & self.wishbone.stb,
+                       [(1, [self.csr.we.eq(self.wishbone.we)]),
+                       (2, [self.wishbone.ack.eq(1)]),
+                       (3, [self.wishbone.ack.eq(0)])])
        
        def get_fragment(self):
                sync = [
-                       self.csr.we_o.eq(0),
-                       self.csr.dat_o.eq(self.wishbone.dat_i[:8]),
-                       self.csr.adr_o.eq(self.wishbone.adr_i[:14]),
-                       self.wishbone.dat_o.eq(self.csr.dat_i)
+                       self.csr.we.eq(0),
+                       self.csr.dat_w.eq(self.wishbone.dat_w[:8]),
+                       self.csr.adr.eq(self.wishbone.adr[:14]),
+                       self.wishbone.dat_r.eq(self.csr.dat_r)
                ]
                return Fragment(sync=sync) + self.timeline.get_fragment()