soc: merge with misoc 3fcc4f116c3292020cb811d179e45ae45990101b
[litex.git] / litex / soc / interconnect / wishbone.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 from litex.gen.genlib.misc import split, displacer, chooser
8 from litex.gen.genlib.fsm import FSM, NextState
9
10 from litex.soc.interconnect import csr
11
12 # TODO: rewrite without FlipFlop and Counter
13
14
15 _layout = [
16 ("adr", 30, DIR_M_TO_S),
17 ("dat_w", "data_width", DIR_M_TO_S),
18 ("dat_r", "data_width", DIR_S_TO_M),
19 ("sel", "sel_width", DIR_M_TO_S),
20 ("cyc", 1, DIR_M_TO_S),
21 ("stb", 1, DIR_M_TO_S),
22 ("ack", 1, DIR_S_TO_M),
23 ("we", 1, DIR_M_TO_S),
24 ("cti", 3, DIR_M_TO_S),
25 ("bte", 2, DIR_M_TO_S),
26 ("err", 1, DIR_S_TO_M)
27 ]
28
29
30 class Interface(Record):
31 def __init__(self, data_width=32):
32 Record.__init__(self, set_layout_parameters(_layout,
33 data_width=data_width,
34 sel_width=data_width//8))
35
36 def _do_transaction(self):
37 yield self.cyc.eq(1)
38 yield self.stb.eq(1)
39 yield
40 while not (yield self.ack):
41 yield
42 yield self.cyc.eq(0)
43 yield self.stb.eq(0)
44
45 def write(self, adr, dat, sel=None):
46 if sel is None:
47 sel = 2**len(self.sel) - 1
48 yield self.adr.eq(adr)
49 yield self.dat_w.eq(dat)
50 yield self.sel.eq(sel)
51 yield self.we.eq(1)
52 yield from self._do_transaction()
53
54 def read(self, adr):
55 yield self.adr.eq(adr)
56 yield self.we.eq(0)
57 yield from self._do_transaction()
58 return (yield self.dat_r)
59
60
61 class InterconnectPointToPoint(Module):
62 def __init__(self, master, slave):
63 self.comb += master.connect(slave)
64
65
66 class Arbiter(Module):
67 def __init__(self, masters, target):
68 self.submodules.rr = roundrobin.RoundRobin(len(masters))
69
70 # mux master->slave signals
71 for name, size, direction in _layout:
72 if direction == DIR_M_TO_S:
73 choices = Array(getattr(m, name) for m in masters)
74 self.comb += getattr(target, name).eq(choices[self.rr.grant])
75
76 # connect slave->master signals
77 for name, size, direction in _layout:
78 if direction == DIR_S_TO_M:
79 source = getattr(target, name)
80 for i, m in enumerate(masters):
81 dest = getattr(m, name)
82 if name == "ack" or name == "err":
83 self.comb += dest.eq(source & (self.rr.grant == i))
84 else:
85 self.comb += dest.eq(source)
86
87 # connect bus requests to round-robin selector
88 reqs = [m.cyc for m in masters]
89 self.comb += self.rr.request.eq(Cat(*reqs))
90
91
92 class Decoder(Module):
93 # slaves is a list of pairs:
94 # 0) function that takes the address signal and returns a FHDL expression
95 # that evaluates to 1 when the slave is selected and 0 otherwise.
96 # 1) wishbone.Slave reference.
97 # register adds flip-flops after the address comparators. Improves timing,
98 # but breaks Wishbone combinatorial feedback.
99 def __init__(self, master, slaves, register=False):
100 ns = len(slaves)
101 slave_sel = Signal(ns)
102 slave_sel_r = Signal(ns)
103
104 # decode slave addresses
105 self.comb += [slave_sel[i].eq(fun(master.adr))
106 for i, (fun, bus) in enumerate(slaves)]
107 if register:
108 self.sync += slave_sel_r.eq(slave_sel)
109 else:
110 self.comb += slave_sel_r.eq(slave_sel)
111
112 # connect master->slaves signals except cyc
113 for slave in slaves:
114 for name, size, direction in _layout:
115 if direction == DIR_M_TO_S and name != "cyc":
116 self.comb += getattr(slave[1], name).eq(getattr(master, name))
117
118 # combine cyc with slave selection signals
119 self.comb += [slave[1].cyc.eq(master.cyc & slave_sel[i])
120 for i, slave in enumerate(slaves)]
121
122 # generate master ack (resp. err) by ORing all slave acks (resp. errs)
123 self.comb += [
124 master.ack.eq(reduce(or_, [slave[1].ack for slave in slaves])),
125 master.err.eq(reduce(or_, [slave[1].err for slave in slaves]))
126 ]
127
128 # mux (1-hot) slave data return
129 masked = [Replicate(slave_sel_r[i], len(master.dat_r)) & slaves[i][1].dat_r for i in range(ns)]
130 self.comb += master.dat_r.eq(reduce(or_, masked))
131
132
133 class InterconnectShared(Module):
134 def __init__(self, masters, slaves, register=False):
135 shared = Interface()
136 self.submodules += Arbiter(masters, shared)
137 self.submodules += Decoder(shared, slaves, register)
138
139
140 class Crossbar(Module):
141 def __init__(self, masters, slaves, register=False):
142 matches, busses = zip(*slaves)
143 access = [[Interface() for j in slaves] for i in masters]
144 # decode each master into its access row
145 for row, master in zip(access, masters):
146 row = list(zip(matches, row))
147 self.submodules += Decoder(master, row, register)
148 # arbitrate each access column onto its slave
149 for column, bus in zip(zip(*access), busses):
150 self.submodules += Arbiter(column, bus)
151
152
153 class DownConverter(Module):
154 """DownConverter
155
156 This module splits Wishbone accesses from a master interface to a smaller
157 slave interface.
158
159 Writes:
160 Writes from master are splitted N writes to the slave. Access is acked when the last
161 access is acked by the slave.
162
163 Reads:
164 Read from master are splitted in N reads to the the slave. Read datas from
165 the slave are cached before being presented concatenated on the last access.
166
167 """
168 def __init__(self, master, slave):
169 dw_from = len(master.dat_r)
170 dw_to = len(slave.dat_w)
171 ratio = dw_from//dw_to
172
173 # # #
174
175 read = Signal()
176 write = Signal()
177
178 counter = Signal(max=ratio)
179 counter_reset = Signal()
180 counter_ce = Signal()
181 self.sync += \
182 If(counter_reset,
183 counter.eq(0)
184 ).Elif(counter_ce,
185 counter.eq(counter + 1)
186 )
187 counter_done = Signal()
188 self.comb += counter_done.eq(counter == ratio-1)
189
190 # Main FSM
191 self.submodules.fsm = fsm = FSM(reset_state="IDLE")
192 fsm.act("IDLE",
193 counter_reset.eq(1),
194 If(master.stb & master.cyc,
195 If(master.we,
196 NextState("WRITE")
197 ).Else(
198 NextState("READ")
199 )
200 )
201 )
202 fsm.act("WRITE",
203 write.eq(1),
204 slave.we.eq(1),
205 slave.cyc.eq(1),
206 If(master.stb & master.cyc,
207 slave.stb.eq(1),
208 If(slave.ack,
209 counter_ce.eq(1),
210 If(counter_done,
211 master.ack.eq(1),
212 NextState("IDLE")
213 )
214 )
215 ).Elif(~master.cyc,
216 NextState("IDLE")
217 )
218 )
219 fsm.act("READ",
220 read.eq(1),
221 slave.cyc.eq(1),
222 If(master.stb & master.cyc,
223 slave.stb.eq(1),
224 If(slave.ack,
225 counter_ce.eq(1),
226 If(counter_done,
227 master.ack.eq(1),
228 NextState("IDLE")
229 )
230 )
231 ).Elif(~master.cyc,
232 NextState("IDLE")
233 )
234 )
235
236 # Address
237 self.comb += [
238 If(counter_done,
239 slave.cti.eq(7) # indicate end of burst
240 ).Else(
241 slave.cti.eq(2)
242 ),
243 slave.adr.eq(Cat(counter, master.adr))
244 ]
245
246 # Datapath
247 cases = {}
248 for i in range(ratio):
249 cases[i] = [
250 slave.sel.eq(master.sel[i*dw_to//8:(i+1)*dw_to]),
251 slave.dat_w.eq(master.dat_w[i*dw_to:(i+1)*dw_to])
252 ]
253 self.comb += Case(counter, cases)
254
255
256 cached_data = Signal(dw_from)
257 self.comb += master.dat_r.eq(Cat(cached_data[dw_to:], slave.dat_r))
258 self.sync += \
259 If(read & counter_ce,
260 cached_data.eq(master.dat_r)
261 )
262
263
264 class UpConverter(Module):
265 """UpConverter
266
267 This module up-converts wishbone accesses and bursts from a master interface
268 to a wider slave interface. This allows efficient use wishbone bursts.
269
270 Writes:
271 Wishbone writes are cached before being written to the slave. Access to
272 the slave is done at the end of a burst or when address reach end of burst
273 addressing.
274
275 Reads:
276 Cache is refilled only at the beginning of each burst, the subsequent
277 reads of a burst use the cached data.
278
279 """
280 def __init__(self, master, slave):
281 dw_from = len(master.dat_r)
282 dw_to = len(slave.dat_w)
283 ratio = dw_to//dw_from
284 ratiobits = log2_int(ratio)
285
286 # # #
287
288 write = Signal()
289 evict = Signal()
290 refill = Signal()
291 read = Signal()
292
293 address = FlipFlop(30)
294 self.submodules += address
295 self.comb += address.d.eq(master.adr)
296
297 counter = Signal(max=ratio)
298 counter_ce = Signal()
299 counter_reset = Signal()
300 self.sync += \
301 If(counter_reset,
302 counter.eq(0)
303 ).Elif(counter_ce,
304 counter.eq(counter + 1)
305 )
306 counter_offset = Signal(max=ratio)
307 counter_done = Signal()
308 self.comb += [
309 counter_offset.eq(address.q),
310 counter_done.eq((counter + counter_offset) == ratio-1)
311 ]
312
313 cached_data = Signal(dw_to)
314 cached_sel = Signal(dw_to//8)
315
316 end_of_burst = Signal()
317 self.comb += end_of_burst.eq(~master.cyc |
318 (master.stb & master.cyc & master.ack & ((master.cti == 7) | counter_done)))
319
320
321 need_refill = FlipFlop(reset=1)
322 self.submodules += need_refill
323 self.comb += [
324 need_refill.reset.eq(end_of_burst),
325 need_refill.d.eq(0)
326 ]
327
328 # Main FSM
329 self.submodules.fsm = fsm = FSM()
330 fsm.act("IDLE",
331 counter_reset.eq(1),
332 If(master.stb & master.cyc,
333 address.ce.eq(1),
334 If(master.we,
335 NextState("WRITE")
336 ).Else(
337 If(need_refill.q,
338 NextState("REFILL")
339 ).Else(
340 NextState("READ")
341 )
342 )
343 )
344 )
345 fsm.act("WRITE",
346 If(master.stb & master.cyc,
347 write.eq(1),
348 counter_ce.eq(1),
349 master.ack.eq(1),
350 If(counter_done,
351 NextState("EVICT")
352 )
353 ).Elif(~master.cyc,
354 NextState("EVICT")
355 )
356 )
357 fsm.act("EVICT",
358 evict.eq(1),
359 slave.stb.eq(1),
360 slave.we.eq(1),
361 slave.cyc.eq(1),
362 slave.dat_w.eq(cached_data),
363 slave.sel.eq(cached_sel),
364 If(slave.ack,
365 NextState("IDLE")
366 )
367 )
368 fsm.act("REFILL",
369 refill.eq(1),
370 slave.stb.eq(1),
371 slave.cyc.eq(1),
372 If(slave.ack,
373 need_refill.ce.eq(1),
374 NextState("READ")
375 )
376 )
377 fsm.act("READ",
378 read.eq(1),
379 If(master.stb & master.cyc,
380 master.ack.eq(1)
381 ),
382 NextState("IDLE")
383 )
384
385 # Address
386 self.comb += [
387 slave.cti.eq(7), # we are not able to generate bursts since up-converting
388 slave.adr.eq(address.q[ratiobits:])
389 ]
390
391 # Datapath
392 cached_datas = [FlipFlop(dw_from) for i in range(ratio)]
393 cached_sels = [FlipFlop(dw_from//8) for i in range(ratio)]
394 self.submodules += cached_datas, cached_sels
395
396 cases = {}
397 for i in range(ratio):
398 write_sel = Signal()
399 cases[i] = write_sel.eq(1)
400 self.comb += [
401 cached_sels[i].reset.eq(counter_reset),
402 If(write,
403 cached_datas[i].d.eq(master.dat_w),
404 ).Else(
405 cached_datas[i].d.eq(slave.dat_r[dw_from*i:dw_from*(i+1)])
406 ),
407 cached_sels[i].d.eq(master.sel),
408 If((write & write_sel) | refill,
409 cached_datas[i].ce.eq(1),
410 cached_sels[i].ce.eq(1)
411 )
412 ]
413 self.comb += Case(counter + counter_offset, cases)
414
415 cases = {}
416 for i in range(ratio):
417 cases[i] = master.dat_r.eq(cached_datas[i].q)
418 self.comb += Case(address.q[:ratiobits], cases)
419
420 self.comb += [
421 cached_data.eq(Cat([cached_data.q for cached_data in cached_datas])),
422 cached_sel.eq(Cat([cached_sel.q for cached_sel in cached_sels]))
423 ]
424
425
426 class Converter(Module):
427 """Converter
428
429 This module is a wrapper for DownConverter and UpConverter.
430 It should preferably be used rather than direct instantiations
431 of specific converters.
432 """
433 def __init__(self, master, slave):
434 self.master = master
435 self.slave = slave
436
437 # # #
438
439 dw_from = len(master.dat_r)
440 dw_to = len(slave.dat_r)
441 if dw_from > dw_to:
442 downconverter = DownConverter(master, slave)
443 self.submodules += downconverter
444 elif dw_from < dw_to:
445 upconverter = UpConverter(master, slave)
446 self.submodules += upconverter
447 else:
448 Record.connect(master, slave)
449
450
451 class Cache(Module):
452 """Cache
453
454 This module is a write-back wishbone cache that can be used as a L2 cache.
455 Cachesize (in 32-bit words) is the size of the data store and must be a power of 2
456 """
457 def __init__(self, cachesize, master, slave):
458 self.master = master
459 self.slave = slave
460
461 ###
462
463 dw_from = len(master.dat_r)
464 dw_to = len(slave.dat_r)
465 if dw_to > dw_from and (dw_to % dw_from) != 0:
466 raise ValueError("Slave data width must be a multiple of {dw}".format(dw=dw_from))
467 if dw_to < dw_from and (dw_from % dw_to) != 0:
468 raise ValueError("Master data width must be a multiple of {dw}".format(dw=dw_to))
469
470 # Split address:
471 # TAG | LINE NUMBER | LINE OFFSET
472 offsetbits = log2_int(max(dw_to//dw_from, 1))
473 addressbits = len(slave.adr) + offsetbits
474 linebits = log2_int(cachesize) - offsetbits
475 tagbits = addressbits - linebits
476 wordbits = log2_int(max(dw_from//dw_to, 1))
477 adr_offset, adr_line, adr_tag = split(master.adr, offsetbits, linebits, tagbits)
478 word = Signal(wordbits) if wordbits else None
479
480 # Data memory
481 data_mem = Memory(dw_to*2**wordbits, 2**linebits)
482 data_port = data_mem.get_port(write_capable=True, we_granularity=8)
483 self.specials += data_mem, data_port
484
485 write_from_slave = Signal()
486 if adr_offset is None:
487 adr_offset_r = None
488 else:
489 adr_offset_r = Signal(offsetbits)
490 self.sync += adr_offset_r.eq(adr_offset)
491
492 self.comb += [
493 data_port.adr.eq(adr_line),
494 If(write_from_slave,
495 displacer(slave.dat_r, word, data_port.dat_w),
496 displacer(Replicate(1, dw_to//8), word, data_port.we)
497 ).Else(
498 data_port.dat_w.eq(Replicate(master.dat_w, max(dw_to//dw_from, 1))),
499 If(master.cyc & master.stb & master.we & master.ack,
500 displacer(master.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True)
501 )
502 ),
503 chooser(data_port.dat_r, word, slave.dat_w),
504 slave.sel.eq(2**(dw_to//8)-1),
505 chooser(data_port.dat_r, adr_offset_r, master.dat_r, reverse=True)
506 ]
507
508
509 # Tag memory
510 tag_layout = [("tag", tagbits), ("dirty", 1)]
511 tag_mem = Memory(layout_len(tag_layout), 2**linebits)
512 tag_port = tag_mem.get_port(write_capable=True)
513 self.specials += tag_mem, tag_port
514 tag_do = Record(tag_layout)
515 tag_di = Record(tag_layout)
516 self.comb += [
517 tag_do.raw_bits().eq(tag_port.dat_r),
518 tag_port.dat_w.eq(tag_di.raw_bits())
519 ]
520
521 self.comb += [
522 tag_port.adr.eq(adr_line),
523 tag_di.tag.eq(adr_tag)
524 ]
525 if word is not None:
526 self.comb += slave.adr.eq(Cat(word, adr_line, tag_do.tag))
527 else:
528 self.comb += slave.adr.eq(Cat(adr_line, tag_do.tag))
529
530 # slave word computation, word_clr and word_inc will be simplified
531 # at synthesis when wordbits=0
532 word_clr = Signal()
533 word_inc = Signal()
534 if word is not None:
535 self.sync += \
536 If(word_clr,
537 word.eq(0),
538 ).Elif(word_inc,
539 word.eq(word+1)
540 )
541
542 def word_is_last(word):
543 if word is not None:
544 return word == 2**wordbits-1
545 else:
546 return 1
547
548 # Control FSM
549 self.submodules.fsm = fsm = FSM(reset_state="IDLE")
550 fsm.act("IDLE",
551 If(master.cyc & master.stb,
552 NextState("TEST_HIT")
553 )
554 )
555 fsm.act("TEST_HIT",
556 word_clr.eq(1),
557 If(tag_do.tag == adr_tag,
558 master.ack.eq(1),
559 If(master.we,
560 tag_di.dirty.eq(1),
561 tag_port.we.eq(1)
562 ),
563 NextState("IDLE")
564 ).Else(
565 If(tag_do.dirty,
566 NextState("EVICT")
567 ).Else(
568 NextState("REFILL_WRTAG")
569 )
570 )
571 )
572
573 fsm.act("EVICT",
574 slave.stb.eq(1),
575 slave.cyc.eq(1),
576 slave.we.eq(1),
577 If(slave.ack,
578 word_inc.eq(1),
579 If(word_is_last(word),
580 NextState("REFILL_WRTAG")
581 )
582 )
583 )
584 fsm.act("REFILL_WRTAG",
585 # Write the tag first to set the slave address
586 tag_port.we.eq(1),
587 word_clr.eq(1),
588 NextState("REFILL")
589 )
590 fsm.act("REFILL",
591 slave.stb.eq(1),
592 slave.cyc.eq(1),
593 slave.we.eq(0),
594 If(slave.ack,
595 write_from_slave.eq(1),
596 word_inc.eq(1),
597 If(word_is_last(word),
598 NextState("TEST_HIT"),
599 ).Else(
600 NextState("REFILL")
601 )
602 )
603 )
604
605
606 class SRAM(Module):
607 def __init__(self, mem_or_size, read_only=None, init=None, bus=None):
608 if bus is None:
609 bus = Interface()
610 self.bus = bus
611 bus_data_width = len(self.bus.dat_r)
612 if isinstance(mem_or_size, Memory):
613 assert(mem_or_size.width <= bus_data_width)
614 self.mem = mem_or_size
615 else:
616 self.mem = Memory(bus_data_width, mem_or_size//(bus_data_width//8), init=init)
617 if read_only is None:
618 if hasattr(self.mem, "bus_read_only"):
619 read_only = self.mem.bus_read_only
620 else:
621 read_only = False
622
623 ###
624
625 # memory
626 port = self.mem.get_port(write_capable=not read_only, we_granularity=8)
627 self.specials += self.mem, port
628 # generate write enable signal
629 if not read_only:
630 self.comb += [port.we[i].eq(self.bus.cyc & self.bus.stb & self.bus.we & self.bus.sel[i])
631 for i in range(4)]
632 # address and data
633 self.comb += [
634 port.adr.eq(self.bus.adr[:len(port.adr)]),
635 self.bus.dat_r.eq(port.dat_r)
636 ]
637 if not read_only:
638 self.comb += port.dat_w.eq(self.bus.dat_w),
639 # generate ack
640 self.sync += [
641 self.bus.ack.eq(0),
642 If(self.bus.cyc & self.bus.stb & ~self.bus.ack, self.bus.ack.eq(1))
643 ]
644
645
646 class CSRBank(csr.GenericBank):
647 def __init__(self, description, bus=None):
648 if bus is None:
649 bus = Interface()
650 self.bus = bus
651
652 ###
653
654 csr.GenericBank.__init__(self, description, len(self.bus.dat_w))
655
656 for i, c in enumerate(self.simple_csrs):
657 self.comb += [
658 c.r.eq(self.bus.dat_w[:c.size]),
659 c.re.eq(self.bus.cyc & self.bus.stb & ~self.bus.ack & self.bus.we & \
660 (self.bus.adr[:self.decode_bits] == i))
661 ]
662
663 brcases = dict((i, self.bus.dat_r.eq(c.w)) for i, c in enumerate(self.simple_csrs))
664 self.sync += [
665 Case(self.bus.adr[:self.decode_bits], brcases),
666 If(bus.ack, bus.ack.eq(0)).Elif(bus.cyc & bus.stb, bus.ack.eq(1))
667 ]