1 # This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
6 from nmigen
import tracer
7 from nmigen
.back
.pysim
import *
9 __ALL__
= ["delayed_enter", "Timeline", "CSRPrefixProxy"]
12 def delayed_enter(m
, src
, dst
, delay
):
13 if not isinstance(m
, Module
):
14 raise ValueError("m must be a module object, not {!r}".format(m
))
15 if not isinstance(delay
, int):
16 raise ValueError("Delay must be an integer, not {!r}".format(delay
))
18 raise ValueError("Delay must be at least one cycle, not {!r}".format(delay
))
20 for i
in range(delay
):
24 statename
= "{}-{}".format(src
, i
)
29 deststate
= "{}-{}".format(src
, i
+1)
31 with m
.State(statename
):
35 class Timeline(Elaboratable
):
36 def __init__(self
, events
):
37 self
.trigger
= Signal()
40 def elaborate(self
, platform
):
43 lastevent
= max([e
[0] for e
in self
._events
])
44 counter
= Signal(range(lastevent
+1))
46 # Counter incrementation
47 # (with overflow handling)
48 if (lastevent
& (lastevent
+ 1)) != 0:
49 with m
.If(counter
== lastevent
):
50 m
.d
.sync
+= counter
.eq(0)
52 with m
.If(counter
!= 0):
53 m
.d
.sync
+= counter
.eq(counter
+1)
54 with m
.Elif(self
.trigger
):
55 m
.d
.sync
+= counter
.eq(1)
57 with m
.If(counter
!= 0):
58 m
.d
.sync
+= counter
.eq(counter
+1)
59 with m
.Elif(self
.trigger
):
60 m
.d
.sync
+= counter
.eq(1)
62 for e
in self
._events
:
64 with m
.If(self
.trigger
& (counter
== 0)):
67 with m
.If(counter
== e
[0]):
74 def __init__(self
, bank
, prefix
):
78 def csr(self
, width
, access
, *, addr
=None, alignment
=None, name
=None,
80 if name
is not None and not isinstance(name
, str):
81 raise TypeError("Name must be a string, not {!r}".format(name
))
82 name
= name
or tracer
.get_var_name(depth
=2 + src_loc_at
).lstrip("_")
84 prefixed_name
= "{}_{}".format(self
._prefix
, name
)
85 return self
._bank
.csr(width
=width
, access
=access
, addr
=addr
,
86 alignment
=alignment
, name
=prefixed_name
)