From: Sebastien Bourdeauducq Date: Wed, 15 Feb 2012 15:30:16 +0000 (+0100) Subject: bus: simplify and cleanup X-Git-Tag: 24jan2021_ls180~2099^2~1019 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=04932121246b8e0e859fbdd0c890f4138ed73109;p=litex.git bus: simplify and cleanup Unify slave and master interfaces Remove signal direction suffixes Generic simple interconnect Wishbone point-to-point interconnect Description filter (get_name) Misc cleanups --- diff --git a/examples/wb_intercon/intercon_conv.py b/examples/wb_intercon/intercon_conv.py index 277bf82d..667d75c2 100644 --- a/examples/wb_intercon/intercon_conv.py +++ b/examples/wb_intercon/intercon_conv.py @@ -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) diff --git a/examples/wb_intercon/tb_intercon.v b/examples/wb_intercon/tb_intercon.v index b424ebad..30b484d1 100644 --- a/examples/wb_intercon/tb_intercon.v +++ b/examples/wb_intercon/tb_intercon.v @@ -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) ); //--------------------------------------------------------------------------- diff --git a/migen/bus/csr.py b/migen/bus/csr.py index 9e009322..9fff20a2 100644 --- a/migen/bus/csr.py +++ b/migen/bus/csr.py @@ -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 diff --git a/migen/bus/simple.py b/migen/bus/simple.py index c4b22177..07c1bb36 100644 --- a/migen/bus/simple.py +++ b/migen/bus/simple.py @@ -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) diff --git a/migen/bus/wishbone.py b/migen/bus/wishbone.py index fa63fedd..ee7719b2 100644 --- a/migen/bus/wishbone.py +++ b/migen/bus/wishbone.py @@ -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 diff --git a/migen/bus/wishbone2asmi.py b/migen/bus/wishbone2asmi.py index c7f35043..23544d0d 100644 --- a/migen/bus/wishbone2asmi.py +++ b/migen/bus/wishbone2asmi.py @@ -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) ), diff --git a/migen/bus/wishbone2csr.py b/migen/bus/wishbone2csr.py index bd5406ee..21114b46 100644 --- a/migen/bus/wishbone2csr.py +++ b/migen/bus/wishbone2csr.py @@ -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()