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