litex: reorganize things, first work working version
[litex.git] / litex / soc / interconnect / lasmi_bus.py
1 from functools import reduce
2 from operator import or_
3
4 from litex.gen import *
5 from litex.gen.genlib import roundrobin
6 from litex.gen.genlib.record import *
7
8
9 class Interface(Record):
10 def __init__(self, aw, dw, nbanks, req_queue_size, read_latency, write_latency):
11 self.aw = aw
12 self.dw = dw
13 self.nbanks = nbanks
14 self.req_queue_size = req_queue_size
15 self.read_latency = read_latency
16 self.write_latency = write_latency
17
18 bank_layout = [
19 ("adr", aw, DIR_M_TO_S),
20 ("we", 1, DIR_M_TO_S),
21 ("stb", 1, DIR_M_TO_S),
22 ("req_ack", 1, DIR_S_TO_M),
23 ("dat_w_ack", 1, DIR_S_TO_M),
24 ("dat_r_ack", 1, DIR_S_TO_M),
25 ("lock", 1, DIR_S_TO_M)
26 ]
27 if nbanks > 1:
28 layout = [("bank"+str(i), bank_layout) for i in range(nbanks)]
29 else:
30 layout = bank_layout
31 layout += [
32 ("dat_w", dw, DIR_M_TO_S),
33 ("dat_we", dw//8, DIR_M_TO_S),
34 ("dat_r", dw, DIR_S_TO_M)
35 ]
36 Record.__init__(self, layout)
37
38
39 def _getattr_all(l, attr):
40 it = iter(l)
41 r = getattr(next(it), attr)
42 for e in it:
43 if getattr(e, attr) != r:
44 raise ValueError
45 return r
46
47
48 class LASMIxbar(Module):
49 def __init__(self, controllers, cba_shift):
50 self._controllers = controllers
51 self._cba_shift = cba_shift
52
53 self._rca_bits = _getattr_all(controllers, "aw")
54 self._dw = _getattr_all(controllers, "dw")
55 self._nbanks = _getattr_all(controllers, "nbanks")
56 self._req_queue_size = _getattr_all(controllers, "req_queue_size")
57 self._read_latency = _getattr_all(controllers, "read_latency")
58 self._write_latency = _getattr_all(controllers, "write_latency")
59
60 self._bank_bits = log2_int(self._nbanks, False)
61 self._controller_bits = log2_int(len(self._controllers), False)
62
63 self._masters = []
64
65 def get_master(self):
66 if self.finalized:
67 raise FinalizeError
68 lasmi_master = Interface(self._rca_bits + self._bank_bits + self._controller_bits,
69 self._dw, 1, self._req_queue_size, self._read_latency, self._write_latency)
70 self._masters.append(lasmi_master)
71 return lasmi_master
72
73 def do_finalize(self):
74 nmasters = len(self._masters)
75
76 m_ca, m_ba, m_rca = self._split_master_addresses(self._controller_bits,
77 self._bank_bits, self._rca_bits, self._cba_shift)
78
79 for nc, controller in enumerate(self._controllers):
80 if self._controller_bits:
81 controller_selected = [ca == nc for ca in m_ca]
82 else:
83 controller_selected = [1]*nmasters
84 master_req_acks = [0]*nmasters
85 master_dat_w_acks = [0]*nmasters
86 master_dat_r_acks = [0]*nmasters
87
88 rrs = [roundrobin.RoundRobin(nmasters, roundrobin.SP_CE) for n in range(self._nbanks)]
89 self.submodules += rrs
90 for nb, rr in enumerate(rrs):
91 bank = getattr(controller, "bank"+str(nb))
92
93 # for each master, determine if another bank locks it
94 master_locked = []
95 for nm, master in enumerate(self._masters):
96 locked = 0
97 for other_nb, other_rr in enumerate(rrs):
98 if other_nb != nb:
99 other_bank = getattr(controller, "bank"+str(other_nb))
100 locked = locked | (other_bank.lock & (other_rr.grant == nm))
101 master_locked.append(locked)
102
103 # arbitrate
104 bank_selected = [cs & (ba == nb) & ~locked for cs, ba, locked in zip(controller_selected, m_ba, master_locked)]
105 bank_requested = [bs & master.stb for bs, master in zip(bank_selected, self._masters)]
106 self.comb += [
107 rr.request.eq(Cat(*bank_requested)),
108 rr.ce.eq(~bank.stb & ~bank.lock)
109 ]
110
111 # route requests
112 self.comb += [
113 bank.adr.eq(Array(m_rca)[rr.grant]),
114 bank.we.eq(Array(self._masters)[rr.grant].we),
115 bank.stb.eq(Array(bank_requested)[rr.grant])
116 ]
117 master_req_acks = [master_req_ack | ((rr.grant == nm) & bank_selected[nm] & bank.req_ack)
118 for nm, master_req_ack in enumerate(master_req_acks)]
119 master_dat_w_acks = [master_dat_w_ack | ((rr.grant == nm) & bank.dat_w_ack)
120 for nm, master_dat_w_ack in enumerate(master_dat_w_acks)]
121 master_dat_r_acks = [master_dat_r_ack | ((rr.grant == nm) & bank.dat_r_ack)
122 for nm, master_dat_r_ack in enumerate(master_dat_r_acks)]
123
124 for nm, master_dat_w_ack in enumerate(master_dat_w_acks):
125 for i in range(self._write_latency):
126 new_master_dat_w_ack = Signal()
127 self.sync += new_master_dat_w_ack.eq(master_dat_w_ack)
128 master_dat_w_ack = new_master_dat_w_ack
129 master_dat_w_acks[nm] = master_dat_w_ack
130
131 for nm, master_dat_r_ack in enumerate(master_dat_r_acks):
132 for i in range(self._read_latency):
133 new_master_dat_r_ack = Signal()
134 self.sync += new_master_dat_r_ack.eq(master_dat_r_ack)
135 master_dat_r_ack = new_master_dat_r_ack
136 master_dat_r_acks[nm] = master_dat_r_ack
137
138 self.comb += [master.req_ack.eq(master_req_ack) for master, master_req_ack in zip(self._masters, master_req_acks)]
139 self.comb += [master.dat_w_ack.eq(master_dat_w_ack) for master, master_dat_w_ack in zip(self._masters, master_dat_w_acks)]
140 self.comb += [master.dat_r_ack.eq(master_dat_r_ack) for master, master_dat_r_ack in zip(self._masters, master_dat_r_acks)]
141
142 # route data writes
143 controller_selected_wl = controller_selected
144 for i in range(self._write_latency):
145 n_controller_selected_wl = [Signal() for i in range(nmasters)]
146 self.sync += [n.eq(o) for n, o in zip(n_controller_selected_wl, controller_selected_wl)]
147 controller_selected_wl = n_controller_selected_wl
148 dat_w_maskselect = []
149 dat_we_maskselect = []
150 for master, selected in zip(self._masters, controller_selected_wl):
151 o_dat_w = Signal(self._dw)
152 o_dat_we = Signal(self._dw//8)
153 self.comb += If(selected,
154 o_dat_w.eq(master.dat_w),
155 o_dat_we.eq(master.dat_we)
156 )
157 dat_w_maskselect.append(o_dat_w)
158 dat_we_maskselect.append(o_dat_we)
159 self.comb += [
160 controller.dat_w.eq(reduce(or_, dat_w_maskselect)),
161 controller.dat_we.eq(reduce(or_, dat_we_maskselect))
162 ]
163
164 # route data reads
165 if self._controller_bits:
166 for master in self._masters:
167 controller_sel = Signal(self._controller_bits)
168 for nc, controller in enumerate(self._controllers):
169 for nb in range(nbanks):
170 bank = getattr(controller, "bank"+str(nb))
171 self.comb += If(bank.stb & bank.ack, controller_sel.eq(nc))
172 for i in range(self._read_latency):
173 n_controller_sel = Signal(self._controller_bits)
174 self.sync += n_controller_sel.eq(controller_sel)
175 controller_sel = n_controller_sel
176 self.comb += master.dat_r.eq(Array(self._controllers)[controller_sel].dat_r)
177 else:
178 self.comb += [master.dat_r.eq(self._controllers[0].dat_r) for master in self._masters]
179
180 def _split_master_addresses(self, controller_bits, bank_bits, rca_bits, cba_shift):
181 m_ca = [] # controller address
182 m_ba = [] # bank address
183 m_rca = [] # row and column address
184 for master in self._masters:
185 cba = Signal(self._controller_bits + self._bank_bits)
186 rca = Signal(self._rca_bits)
187 cba_upper = cba_shift + controller_bits + bank_bits
188 self.comb += cba.eq(master.adr[cba_shift:cba_upper])
189 if cba_shift < self._rca_bits:
190 if cba_shift:
191 self.comb += rca.eq(Cat(master.adr[:cba_shift], master.adr[cba_upper:]))
192 else:
193 self.comb += rca.eq(master.adr[cba_upper:])
194 else:
195 self.comb += rca.eq(master.adr[:cba_shift])
196
197 if self._controller_bits:
198 ca = Signal(self._controller_bits)
199 ba = Signal(self._bank_bits)
200 self.comb += Cat(ba, ca).eq(cba)
201 else:
202 ca = None
203 ba = cba
204
205 m_ca.append(ca)
206 m_ba.append(ba)
207 m_rca.append(rca)
208 return m_ca, m_ba, m_rca