1 # This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
4 from nmigen
import tracer
5 from nmigen
.compat
import Case
7 __ALL__
= ["delayed_enter", "RoundRobin", "Timeline", "CSRPrefixProxy"]
9 def delayed_enter(m
, src
, dst
, delay
):
12 for i
in range(delay
):
16 statename
= "{}-{}".format(src
, i
)
21 deststate
= "{}-{}".format(src
, i
+1)
23 with m
.State(statename
):
26 # Original nMigen implementation by HarryHo90sHK
27 class RoundRobin(Elaboratable
):
28 """A round-robin scheduler.
32 Maximum number of requests to handle.
36 Signal where a '1' on the i-th bit represents an incoming request from the i-th device.
37 grant : Signal(range(n))
38 Signal that equals to the index of the device which is currently granted access.
40 Strobe signal to enable granting access to the next device requesting. Externally driven.
42 def __init__(self
, n
):
44 self
.request
= Signal(n
)
45 self
.grant
= Signal(range(n
))
48 def elaborate(self
, platform
):
52 with m
.Switch(self
.grant
):
53 for i
in range(self
.n
):
55 for j
in reversed(range(i
+1, i
+self
.n
)):
56 # If i+1 <= j < n, then t == j; (after i)
57 # If n <= j < i+n, then t == j - n (before i)
59 with m
.If(self
.request
[t
]):
60 m
.d
.sync
+= self
.grant
.eq(t
)
64 class Timeline(Elaboratable
):
65 def __init__(self
, events
):
66 self
.trigger
= Signal()
69 def elaborate(self
, platform
):
72 lastevent
= max([e
[0] for e
in self
._events
])
73 counter
= Signal(range(lastevent
+1))
75 # Counter incrementation
76 # (with overflow handling)
77 if (lastevent
& (lastevent
+ 1)) != 0:
78 with m
.If(counter
== lastevent
):
79 m
.d
.sync
+= counter
.eq(0)
81 with m
.If(counter
!= 0):
82 m
.d
.sync
+= counter
.eq(counter
+1)
83 with m
.Elif(self
.trigger
):
84 m
.d
.sync
+= counter
.eq(1)
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)
91 for e
in self
._events
:
93 with m
.If(self
.trigger
& (counter
== 0)):
96 with m
.If(counter
== e
[0]):
101 class CSRPrefixProxy
:
102 def __init__(self
, bank
, prefix
):
104 self
._prefix
= prefix
106 def csr(self
, width
, access
, *, addr
=None, alignment
=None, name
=None,
108 if name
is not None and not isinstance(name
, str):
109 raise TypeError("Name must be a string, not {!r}".format(name
))
110 name
= name
or tracer
.get_var_name(depth
=2 + src_loc_at
).lstrip("_")
112 prefixed_name
= "{}_{}".format(self
._prefix
, name
)
113 return self
._bank
.csr(width
=width
, access
=access
, addr
=addr
,
114 alignment
=alignment
, name
=prefixed_name
)