Remove unused code
[gram.git] / gram / compat.py
1 # This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
2
3 from nmigen import *
4 from nmigen import tracer
5 from nmigen.compat import Case
6
7 __ALL__ = ["delayed_enter", "RoundRobin", "Timeline", "CSRPrefixProxy"]
8
9
10 def delayed_enter(m, src, dst, delay):
11 assert delay > 0
12
13 for i in range(delay):
14 if i == 0:
15 statename = src
16 else:
17 statename = "{}-{}".format(src, i)
18
19 if i == delay-1:
20 deststate = dst
21 else:
22 deststate = "{}-{}".format(src, i+1)
23
24 with m.State(statename):
25 m.next = deststate
26
27 # Original nMigen implementation by HarryHo90sHK
28
29
30 class RoundRobin(Elaboratable):
31 """A round-robin scheduler.
32 Parameters
33 ----------
34 n : int
35 Maximum number of requests to handle.
36 Attributes
37 ----------
38 request : Signal(n)
39 Signal where a '1' on the i-th bit represents an incoming request from the i-th device.
40 grant : Signal(range(n))
41 Signal that equals to the index of the device which is currently granted access.
42 stb : Signal()
43 Strobe signal to enable granting access to the next device requesting. Externally driven.
44 """
45
46 def __init__(self, n):
47 self.n = n
48 self.request = Signal(n)
49 self.grant = Signal(range(n))
50 self.stb = Signal()
51
52 def elaborate(self, platform):
53 m = Module()
54
55 with m.If(self.stb):
56 with m.Switch(self.grant):
57 for i in range(self.n):
58 with m.Case(i):
59 for j in reversed(range(i+1, i+self.n)):
60 # If i+1 <= j < n, then t == j; (after i)
61 # If n <= j < i+n, then t == j - n (before i)
62 t = j % self.n
63 with m.If(self.request[t]):
64 m.d.sync += self.grant.eq(t)
65
66 return m
67
68
69 class Timeline(Elaboratable):
70 def __init__(self, events):
71 self.trigger = Signal()
72 self._events = events
73
74 def elaborate(self, platform):
75 m = Module()
76
77 lastevent = max([e[0] for e in self._events])
78 counter = Signal(range(lastevent+1))
79
80 # Counter incrementation
81 # (with overflow handling)
82 if (lastevent & (lastevent + 1)) != 0:
83 with m.If(counter == lastevent):
84 m.d.sync += counter.eq(0)
85 with m.Else():
86 with m.If(counter != 0):
87 m.d.sync += counter.eq(counter+1)
88 with m.Elif(self.trigger):
89 m.d.sync += counter.eq(1)
90 else:
91 with m.If(counter != 0):
92 m.d.sync += counter.eq(counter+1)
93 with m.Elif(self.trigger):
94 m.d.sync += counter.eq(1)
95
96 for e in self._events:
97 if e[0] == 0:
98 with m.If(self.trigger & (counter == 0)):
99 m.d.sync += e[1]
100 else:
101 with m.If(counter == e[0]):
102 m.d.sync += e[1]
103
104 return m
105
106
107 class CSRPrefixProxy:
108 def __init__(self, bank, prefix):
109 self._bank = bank
110 self._prefix = prefix
111
112 def csr(self, width, access, *, addr=None, alignment=None, name=None,
113 src_loc_at=0):
114 if name is not None and not isinstance(name, str):
115 raise TypeError("Name must be a string, not {!r}".format(name))
116 name = name or tracer.get_var_name(depth=2 + src_loc_at).lstrip("_")
117
118 prefixed_name = "{}_{}".format(self._prefix, name)
119 return self._bank.csr(width=width, access=access, addr=addr,
120 alignment=alignment, name=prefixed_name)