Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Kestrel Collaboration
Kestrel LiteX
migen
Commits
680a3446
Commit
680a3446
authored
12 years ago
by
Sebastien Bourdeauducq
Browse files
Options
Download
Email Patches
Plain Diff
flow: refactor scheduling models
parent
493b181a
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
90 additions
and
113 deletions
+90
-113
migen/actorlib/control.py
migen/actorlib/control.py
+1
-1
migen/flow/actor.py
migen/flow/actor.py
+77
-92
migen/flow/ala.py
migen/flow/ala.py
+4
-6
migen/flow/network.py
migen/flow/network.py
+1
-2
migen/flow/plumbing.py
migen/flow/plumbing.py
+7
-12
No files found.
migen/actorlib/control.py
View file @
680a3446
...
@@ -20,7 +20,7 @@ class For(Actor):
...
@@ -20,7 +20,7 @@ class For(Actor):
for
n
,
bv
in
enumerate
(
self
.
d_bv
)]
for
n
,
bv
in
enumerate
(
self
.
d_bv
)]
l_source
=
[(
"d{0}"
.
format
(
n
),
bv
)
l_source
=
[(
"d{0}"
.
format
(
n
),
bv
)
for
n
,
bv
in
enumerate
(
self
.
d_bv
)]
for
n
,
bv
in
enumerate
(
self
.
d_bv
)]
Actor
.
__init__
(
self
,
SchedulingModel
(
SchedulingModel
.
DYNAMIC
),
Actor
.
__init__
(
self
,
(
"sink"
,
Sink
,
l_sink
),
(
"sink"
,
Sink
,
l_sink
),
(
"source"
,
Source
,
l_source
))
(
"source"
,
Source
,
l_source
))
...
...
This diff is collapsed.
Click to expand it.
migen/flow/actor.py
View file @
680a3446
...
@@ -2,25 +2,6 @@ from migen.fhdl.structure import *
...
@@ -2,25 +2,6 @@ from migen.fhdl.structure import *
from
migen.corelogic.misc
import
optree
from
migen.corelogic.misc
import
optree
from
migen.corelogic.record
import
*
from
migen.corelogic.record
import
*
class
SchedulingModel
:
COMBINATORIAL
,
SEQUENTIAL
,
PIPELINE
,
DYNAMIC
=
range
(
4
)
def
__init__
(
self
,
model
,
latency
=
1
):
self
.
model
=
model
self
.
latency
=
latency
def
__repr__
(
self
):
if
self
.
model
==
SchedulingModel
.
COMBINATORIAL
:
return
"<SchedulingModel: COMBINATORIAL>"
elif
self
.
model
==
SchedulingModel
.
SEQUENTIAL
:
return
"<SchedulingModel: SEQUENTIAL({0})>"
.
format
(
self
.
latency
)
elif
self
.
model
==
SchedulingModel
.
PIPELINE
:
return
"<SchedulingModel: PIPELINE({0})>"
.
format
(
self
.
latency
)
elif
self
.
model
==
SchedulingModel
.
DYNAMIC
:
return
"<SchedulingModel: DYNAMIC>"
else
:
raise
AttributeError
class
Endpoint
:
class
Endpoint
:
def
__init__
(
self
,
token
):
def
__init__
(
self
,
token
):
self
.
token
=
token
self
.
token
=
token
...
@@ -51,55 +32,8 @@ class Source(Endpoint):
...
@@ -51,55 +32,8 @@ class Source(Endpoint):
def
__repr__
(
self
):
def
__repr__
(
self
):
return
"<Source "
+
str
(
self
.
token
)
+
">"
return
"<Source "
+
str
(
self
.
token
)
+
">"
def
_control_fragment_comb
(
stb_i
,
ack_o
,
stb_o
,
ack_i
,
busy
):
return
Fragment
([
stb_o
.
eq
(
stb_i
),
ack_o
.
eq
(
ack_i
),
busy
.
eq
(
0
)])
def
_control_fragment_seq
(
latency
,
stb_i
,
ack_o
,
stb_o
,
ack_i
,
busy
,
trigger
):
ready
=
Signal
()
timer
=
Signal
(
BV
(
bits_for
(
latency
)))
comb
=
[
ready
.
eq
(
timer
==
0
)]
sync
=
[
If
(
trigger
,
timer
.
eq
(
latency
)
).
Elif
(
~
ready
,
timer
.
eq
(
timer
-
1
)
)
]
mask
=
Signal
()
comb
+=
[
stb_o
.
eq
(
ready
&
mask
),
trigger
.
eq
(
stb_i
&
(
ack_i
|
~
mask
)
&
ready
),
ack_o
.
eq
(
trigger
),
busy
.
eq
(
~
ready
)
]
sync
+=
[
If
(
trigger
,
mask
.
eq
(
1
)),
If
(
stb_o
&
ack_i
,
mask
.
eq
(
0
))
]
return
Fragment
(
comb
,
sync
)
def
_control_fragment_pipe
(
latency
,
stb_i
,
ack_o
,
stb_o
,
ack_i
,
busy
,
pipe_ce
):
valid
=
Signal
(
BV
(
latency
))
if
latency
>
1
:
sync
=
[
If
(
pipe_ce
,
valid
.
eq
(
Cat
(
stb_i
,
valid
[:
latency
-
1
])))]
else
:
sync
=
[
If
(
pipe_ce
,
valid
.
eq
(
stb_i
))]
last_valid
=
valid
[
latency
-
1
]
comb
=
[
pipe_ce
.
eq
(
ack_i
|
~
last_valid
),
ack_o
.
eq
(
pipe_ce
),
stb_o
.
eq
(
last_valid
),
busy
.
eq
(
optree
(
"|"
,
[
valid
[
i
]
for
i
in
range
(
latency
)]))
]
return
Fragment
(
comb
,
sync
)
class
Actor
:
class
Actor
:
def
__init__
(
self
,
scheduling_model
,
*
endpoint_descriptions
,
endpoints
=
None
):
def
__init__
(
self
,
*
endpoint_descriptions
,
endpoints
=
None
):
self
.
scheduling_model
=
scheduling_model
if
endpoints
is
None
:
if
endpoints
is
None
:
self
.
endpoints
=
{}
self
.
endpoints
=
{}
for
desc
in
endpoint_descriptions
:
for
desc
in
endpoint_descriptions
:
...
@@ -113,11 +47,7 @@ class Actor:
...
@@ -113,11 +47,7 @@ class Actor:
else
:
else
:
self
.
endpoints
=
endpoints
self
.
endpoints
=
endpoints
self
.
busy
=
Signal
()
self
.
busy
=
Signal
()
if
self
.
scheduling_model
.
model
==
SchedulingModel
.
SEQUENTIAL
:
self
.
trigger
=
Signal
()
elif
self
.
scheduling_model
.
model
==
SchedulingModel
.
PIPELINE
:
self
.
pipe_ce
=
Signal
()
def
token
(
self
,
ep
):
def
token
(
self
,
ep
):
return
self
.
endpoints
[
ep
].
token
return
self
.
endpoints
[
ep
].
token
...
@@ -131,27 +61,10 @@ class Actor:
...
@@ -131,27 +61,10 @@ class Actor:
return
self
.
filter_endpoints
(
Source
)
return
self
.
filter_endpoints
(
Source
)
def
get_control_fragment
(
self
):
def
get_control_fragment
(
self
):
def
get_single_ep
(
l
):
raise
NotImplementedError
(
"Actor classes must overload get_control_fragment or get_fragment"
)
if
len
(
l
)
!=
1
:
raise
ValueError
(
"Actors with automatic control fragment must have exactly one sink and one source. Consider using plumbing actors."
)
return
self
.
endpoints
[
l
[
0
]]
sink
=
get_single_ep
(
self
.
sinks
())
source
=
get_single_ep
(
self
.
sources
())
stb_i
=
sink
.
stb
ack_o
=
sink
.
ack
stb_o
=
source
.
stb
ack_i
=
source
.
ack
if
self
.
scheduling_model
.
model
==
SchedulingModel
.
COMBINATORIAL
:
return
_control_fragment_comb
(
stb_i
,
ack_o
,
stb_o
,
ack_i
,
self
.
busy
)
elif
self
.
scheduling_model
.
model
==
SchedulingModel
.
SEQUENTIAL
:
return
_control_fragment_seq
(
self
.
scheduling_model
.
latency
,
stb_i
,
ack_o
,
stb_o
,
ack_i
,
self
.
busy
,
self
.
trigger
)
elif
self
.
scheduling_model
.
model
==
SchedulingModel
.
PIPELINE
:
return
_control_fragment_pipe
(
self
.
scheduling_model
.
latency
,
stb_i
,
ack_o
,
stb_o
,
ack_i
,
self
.
busy
,
self
.
pipe_ce
)
elif
self
.
scheduling_model
.
model
==
SchedulingModel
.
DYNAMIC
:
raise
NotImplementedError
(
"Actor classes with dynamic scheduling must overload get_control_fragment or get_fragment"
)
def
get_process_fragment
(
self
):
def
get_process_fragment
(
self
):
raise
NotImplementedError
(
"Actor classes must overload get_process_fragment"
)
raise
NotImplementedError
(
"Actor classes must overload get_process_fragment
or get_fragment
"
)
def
get_fragment
(
self
):
def
get_fragment
(
self
):
return
self
.
get_control_fragment
()
+
self
.
get_process_fragment
()
return
self
.
get_control_fragment
()
+
self
.
get_process_fragment
()
...
@@ -159,6 +72,78 @@ class Actor:
...
@@ -159,6 +72,78 @@ class Actor:
def
__repr__
(
self
):
def
__repr__
(
self
):
return
"<"
+
self
.
__class__
.
__name__
+
" "
+
repr
(
self
.
scheduling_model
)
+
" "
+
repr
(
self
.
sinks
())
+
" "
+
repr
(
self
.
sources
())
+
">"
return
"<"
+
self
.
__class__
.
__name__
+
" "
+
repr
(
self
.
scheduling_model
)
+
" "
+
repr
(
self
.
sinks
())
+
" "
+
repr
(
self
.
sources
())
+
">"
class
BinaryActor
(
Actor
):
def
get_binary_control_fragment
(
self
,
stb_i
,
ack_o
,
stb_o
,
ack_i
):
raise
NotImplementedError
(
"Binary actor classes must overload get_binary_control_fragment"
)
def
get_control_fragment
(
self
):
def
get_single_ep
(
l
):
if
len
(
l
)
!=
1
:
raise
ValueError
(
"Binary actors have exactly one sink and one source. Consider using plumbing actors."
)
return
self
.
endpoints
[
l
[
0
]]
sink
=
get_single_ep
(
self
.
sinks
())
source
=
get_single_ep
(
self
.
sources
())
return
self
.
get_binary_control_fragment
(
sink
.
stb
,
sink
.
ack
,
source
.
stb
,
source
.
ack
)
class
CombinatorialActor
(
BinaryActor
):
def
get_binary_control_fragment
(
self
,
stb_i
,
ack_o
,
stb_o
,
ack_i
):
return
Fragment
([
stb_o
.
eq
(
stb_i
),
ack_o
.
eq
(
ack_i
),
self
.
busy
.
eq
(
0
)])
class
SequentialActor
(
BinaryActor
):
def
__init__
(
self
,
delay
,
*
endpoint_descriptions
,
endpoints
=
None
):
self
.
delay
=
delay
self
.
trigger
=
Signal
()
BinaryActor
.
__init__
(
*
endpoint_descriptions
,
endpoints
=
endpoints
)
def
get_binary_control_fragment
(
self
,
stb_i
,
ack_o
,
stb_o
,
ack_i
):
ready
=
Signal
()
timer
=
Signal
(
BV
(
bits_for
(
self
.
delay
)))
comb
=
[
ready
.
eq
(
timer
==
0
)]
sync
=
[
If
(
self
.
trigger
,
timer
.
eq
(
self
.
delay
)
).
Elif
(
~
ready
,
timer
.
eq
(
timer
-
1
)
)
]
mask
=
Signal
()
comb
+=
[
stb_o
.
eq
(
ready
&
mask
),
self
.
trigger
.
eq
(
stb_i
&
(
ack_i
|
~
mask
)
&
ready
),
ack_o
.
eq
(
self
.
trigger
),
busy
.
eq
(
~
ready
)
]
sync
+=
[
If
(
self
.
trigger
,
mask
.
eq
(
1
)),
If
(
stb_o
&
ack_i
,
mask
.
eq
(
0
))
]
return
Fragment
(
comb
,
sync
)
class
PipelinedActor
(
BinaryActor
):
def
__init__
(
self
,
latency
,
*
endpoint_descriptions
,
endpoints
=
None
):
self
.
latency
=
latency
self
.
pipe_ce
=
Signal
()
BinaryActor
.
__init__
(
*
endpoint_descriptions
,
endpoints
=
endpoints
)
def
get_binary_control_fragment
(
self
,
stb_i
,
ack_o
,
stb_o
,
ack_i
):
valid
=
Signal
(
BV
(
self
.
latency
))
if
self
.
latency
>
1
:
sync
=
[
If
(
self
.
pipe_ce
,
valid
.
eq
(
Cat
(
stb_i
,
valid
[:
self
.
latency
-
1
])))]
else
:
sync
=
[
If
(
self
.
pipe_ce
,
valid
.
eq
(
stb_i
))]
last_valid
=
valid
[
self
.
latency
-
1
]
comb
=
[
self
.
pipe_ce
.
eq
(
ack_i
|
~
last_valid
),
ack_o
.
eq
(
self
.
pipe_ce
),
stb_o
.
eq
(
last_valid
),
busy
.
eq
(
optree
(
"|"
,
[
valid
[
i
]
for
i
in
range
(
self
.
latency
)]))
]
return
Fragment
(
comb
,
sync
)
def
get_conn_fragment
(
source
,
sink
):
def
get_conn_fragment
(
source
,
sink
):
assert
isinstance
(
source
,
Source
)
assert
isinstance
(
source
,
Source
)
assert
isinstance
(
sink
,
Sink
)
assert
isinstance
(
sink
,
Sink
)
...
...
This diff is collapsed.
Click to expand it.
migen/flow/ala.py
View file @
680a3446
...
@@ -4,11 +4,10 @@ from migen.flow.actor import *
...
@@ -4,11 +4,10 @@ from migen.flow.actor import *
from
migen.corelogic.record
import
*
from
migen.corelogic.record
import
*
from
migen.corelogic
import
divider
from
migen.corelogic
import
divider
class
_SimpleBinary
(
Actor
):
class
_SimpleBinary
(
Combinatorial
Actor
):
def
__init__
(
self
,
op
,
bv_op
,
bv_r
):
def
__init__
(
self
,
op
,
bv_op
,
bv_r
):
self
.
op
=
op
self
.
op
=
op
Actor
.
__init__
(
self
,
CombinatorialActor
.
__init__
(
self
,
SchedulingModel
(
SchedulingModel
.
COMBINATORIAL
),
(
"operands"
,
Sink
,
[(
"a"
,
bv_op
),
(
"b"
,
bv_op
)]),
(
"operands"
,
Sink
,
[(
"a"
,
bv_op
),
(
"b"
,
bv_op
)]),
(
"result"
,
Source
,
[(
"r"
,
bv_r
)]))
(
"result"
,
Source
,
[(
"r"
,
bv_r
)]))
...
@@ -58,11 +57,10 @@ class NE(_SimpleBinary):
...
@@ -58,11 +57,10 @@ class NE(_SimpleBinary):
def
__init__
(
self
,
bv
):
def
__init__
(
self
,
bv
):
_SimpleBinary
.
__init__
(
self
,
"!="
,
bv
,
BV
(
1
))
_SimpleBinary
.
__init__
(
self
,
"!="
,
bv
,
BV
(
1
))
class
DivMod
(
Actor
):
class
DivMod
(
Sequential
Actor
):
def
__init__
(
self
,
width
):
def
__init__
(
self
,
width
):
self
.
div
=
divider
.
Divider
(
width
)
self
.
div
=
divider
.
Divider
(
width
)
Actor
.
__init__
(
self
,
SequentialActor
.
__init__
(
self
,
width
,
SchedulingModel
(
SchedulingModel
.
SEQUENTIAL
,
width
),
(
"operands"
,
Sink
,
[(
"dividend"
,
self
.
div
.
dividend_i
),
(
"divisor"
,
self
.
div
.
divisor_i
)]),
(
"operands"
,
Sink
,
[(
"dividend"
,
self
.
div
.
dividend_i
),
(
"divisor"
,
self
.
div
.
divisor_i
)]),
(
"result"
,
Source
,
[(
"quotient"
,
self
.
div
.
quotient_o
),
(
"remainder"
,
self
.
div
.
remainder_o
)]))
(
"result"
,
Source
,
[(
"quotient"
,
self
.
div
.
quotient_o
),
(
"remainder"
,
self
.
div
.
remainder_o
)]))
...
...
This diff is collapsed.
Click to expand it.
migen/flow/network.py
View file @
680a3446
...
@@ -7,8 +7,7 @@ from migen.corelogic.misc import optree
...
@@ -7,8 +7,7 @@ from migen.corelogic.misc import optree
class
CompositeActor
(
Actor
):
class
CompositeActor
(
Actor
):
def
__init__
(
self
,
dfg
):
# TODO: endpoints
def
__init__
(
self
,
dfg
):
# TODO: endpoints
self
.
dfg
=
dfg
self
.
dfg
=
dfg
Actor
.
__init__
(
self
,
Actor
.
__init__
(
self
)
SchedulingModel
(
SchedulingModel
.
DYNAMIC
))
def
get_fragment
(
self
):
def
get_fragment
(
self
):
this_fragments
=
[
get_conn_fragment
(
x
[
0
].
endpoints
[
x
[
2
][
"source"
]],
x
[
1
].
endpoints
[
x
[
2
][
"sink"
]])
this_fragments
=
[
get_conn_fragment
(
x
[
0
].
endpoints
[
x
[
2
][
"source"
]],
x
[
1
].
endpoints
[
x
[
2
][
"sink"
]])
...
...
This diff is collapsed.
Click to expand it.
migen/flow/plumbing.py
View file @
680a3446
...
@@ -3,10 +3,9 @@ from migen.flow.actor import *
...
@@ -3,10 +3,9 @@ from migen.flow.actor import *
from
migen.corelogic.record
import
*
from
migen.corelogic.record
import
*
from
migen.corelogic.misc
import
optree
from
migen.corelogic.misc
import
optree
class
Buffer
(
Actor
):
class
Buffer
(
Pipelined
Actor
):
def
__init__
(
self
,
layout
):
def
__init__
(
self
,
layout
):
Actor
.
__init__
(
self
,
PipelinedActor
.
__init__
(
self
,
1
,
SchedulingModel
(
SchedulingModel
.
PIPELINE
,
1
),
(
"d"
,
Sink
,
layout
),
(
"q"
,
Source
,
layout
))
(
"d"
,
Sink
,
layout
),
(
"q"
,
Source
,
layout
))
def
get_process_fragment
(
self
):
def
get_process_fragment
(
self
):
...
@@ -15,17 +14,15 @@ class Buffer(Actor):
...
@@ -15,17 +14,15 @@ class Buffer(Actor):
sync
=
[
If
(
self
.
pipe_ce
,
Cat
(
*
sigs_q
).
eq
(
Cat
(
*
sigs_d
)))]
sync
=
[
If
(
self
.
pipe_ce
,
Cat
(
*
sigs_q
).
eq
(
Cat
(
*
sigs_d
)))]
return
Fragment
(
sync
=
sync
)
return
Fragment
(
sync
=
sync
)
class
Combinator
(
Actor
):
class
Combinator
(
Combinatorial
Actor
):
def
__init__
(
self
,
layout
,
*
subrecords
):
def
__init__
(
self
,
layout
,
*
subrecords
):
source
=
Record
(
layout
)
source
=
Record
(
layout
)
subrecords
=
[
source
.
subrecord
(
*
subr
)
for
subr
in
subrecords
]
subrecords
=
[
source
.
subrecord
(
*
subr
)
for
subr
in
subrecords
]
eps
=
[(
"sink{0}"
.
format
(
n
),
Sink
,
r
)
eps
=
[(
"sink{0}"
.
format
(
n
),
Sink
,
r
)
for
x
in
enumerate
(
subrecords
)]
for
n
,
r
in
enumerate
(
subrecords
)]
ep_source
=
(
"source"
,
Source
,
source
)
ep_source
=
(
"source"
,
Source
,
source
)
eps
.
append
(
ep_source
)
eps
.
append
(
ep_source
)
Actor
.
__init__
(
self
,
CombinatorialActor
.
__init__
(
self
,
*
eps
)
SchedulingModel
(
SchedulingModel
.
COMBINATORIAL
),
*
eps
)
def
get_fragment
(
self
):
def
get_fragment
(
self
):
source
=
self
.
endpoints
[
"source"
]
source
=
self
.
endpoints
[
"source"
]
...
@@ -35,7 +32,7 @@ class Combinator(Actor):
...
@@ -35,7 +32,7 @@ class Combinator(Actor):
comb
+=
[
sink
.
ack
.
eq
(
source
.
ack
&
source
.
stb
)
for
sink
in
sinks
]
comb
+=
[
sink
.
ack
.
eq
(
source
.
ack
&
source
.
stb
)
for
sink
in
sinks
]
return
Fragment
(
comb
)
return
Fragment
(
comb
)
class
Splitter
(
Actor
):
class
Splitter
(
Combinatorial
Actor
):
def
__init__
(
self
,
layout
,
*
subrecords
):
def
__init__
(
self
,
layout
,
*
subrecords
):
sink
=
Record
(
layout
)
sink
=
Record
(
layout
)
subrecords
=
[
sink
.
subrecord
(
*
subr
)
for
subr
in
subrecords
]
subrecords
=
[
sink
.
subrecord
(
*
subr
)
for
subr
in
subrecords
]
...
@@ -43,8 +40,6 @@ class Splitter(Actor):
...
@@ -43,8 +40,6 @@ class Splitter(Actor):
for
n
,
r
in
enumerate
(
subrecords
)]
for
n
,
r
in
enumerate
(
subrecords
)]
ep_sink
=
(
"sink"
,
Sink
,
sink
)
ep_sink
=
(
"sink"
,
Sink
,
sink
)
eps
.
append
(
ep_sink
)
eps
.
append
(
ep_sink
)
Actor
.
__init__
(
self
,
CombinatorialActor
.
__init__
(
self
,
*
eps
)
SchedulingModel
(
SchedulingModel
.
COMBINATORIAL
),
*
eps
)
# TODO def get_fragment(self):
# TODO def get_fragment(self):
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment