Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
H
HDL
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Jira
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
RTSD
HDL
Commits
63d448b7
Commit
63d448b7
authored
9 years ago
by
Daniel van der Schuur
Browse files
Options
Downloads
Patches
Plain Diff
-SVN copied component_class.py from the prestudy dir to here.
parent
245adf2d
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
tools/oneclick/components/component.py
+460
-0
460 additions, 0 deletions
tools/oneclick/components/component.py
with
460 additions
and
0 deletions
tools/oneclick/components/component.py
0 → 100644
+
460
−
0
View file @
63d448b7
import
multiprocessing
as
mp
import
time
import
common
as
cm
###############################################################################
# Base classes
###############################################################################
class
Signal
(
object
):
def
__init__
(
self
,
name
,
stype
):
self
.
name
=
name
self
.
stype
=
stype
self
.
vhdl_signal_declaration
=
'
SIGNAL %s : %s;
\n
'
%
(
name
,
stype
)
class
StreamPort
(
object
):
def
__init__
(
self
,
component_name
,
name
,
mode
,
stream_index
,
data_width
):
self
.
component_name
=
component_name
if
stream_index
!=
None
:
self
.
name
=
name
+
'
[
'
+
str
(
stream_index
)
+
'
]
'
else
:
self
.
name
=
name
self
.
mode
=
mode
self
.
stream_index
=
stream_index
self
.
data_width
=
data_width
self
.
pipe_end
=
None
self
.
port_type
=
'
t_dp_sosi
'
self
.
signal
=
Signal
(
component_name
+
'
_
'
+
name
,
self
.
port_type
)
#'>' operator: Connect
def
__gt__
(
self
,
other
):
return
self
.
__connect__
(
other
)
def
__connect__
(
self
,
other
):
if
not
(
self
.
pipe_end
==
None
):
# The pipe end is already assigned, this is the case for composite components that
# have wired their entity port to internal instance ports.
# If self is a source port (mode='out'), this means that self.pipe_end is already occupied
# with a pipe sink end from which this entity port receives from an internal source entity.
# To make a connection between other and self, all we need to do is move the existing pipe's snk end
# from self to other. The source end remains connected to self's internal instance.
other
.
pipe_end
=
self
.
pipe_end
elif
not
(
other
.
pipe_end
==
None
):
# The pipe end is already assigned, this is the case for composite components that
# have wired their entity port to internal instance ports.
# If other is a sink port (mode='in'), this means that other.pipe_end is already occupied
# with a pipe source end from which this entity port send to an internal sink entity.
# To make a connection between other and self, all we need to do is move the existing pipe's src end
# from other to self. The sink end remains connected to other's internal instance.
self
.
pipe_end
=
other
.
pipe_end
else
:
snk_end
,
src_end
=
mp
.
Pipe
(
duplex
=
False
)
self
.
pipe_end
=
src_end
other
.
pipe_end
=
snk_end
return
Connection
(
(
self
.
component_name
,
self
.
name
),
(
other
.
component_name
,
other
.
name
)
)
def
send
(
self
,
item
):
self
.
pipe_end
.
send
(
item
)
def
recv
(
self
):
while
True
:
try
:
yield
self
.
pipe_end
.
recv
()
except
EOFError
:
break
class
StreamPortArray
(
list
):
def
__init__
(
self
,
component_name
,
name
,
mode
,
nof_streams
,
data_width
):
list
.
__init__
(
self
)
self
.
component_name
=
component_name
self
.
name
=
name
self
.
mode
=
mode
self
.
nof_streams
=
nof_streams
self
.
data_width
=
data_width
for
stream_index
in
range
(
nof_streams
):
self
.
append
(
StreamPort
(
component_name
,
name
,
mode
,
stream_index
,
data_width
))
self
.
port_type
=
'
t_dp_sosi_arr(%s-1 DOWNTO 0)
'
%
nof_streams
self
.
signal
=
Signal
(
component_name
+
'
_
'
+
name
,
self
.
port_type
)
#'>' operator: Connect
def
__gt__
(
self
,
other
):
return
self
.
__connect__
(
other
)
def
__connect__
(
self
,
other
):
for
stream_port_self
,
stream_port_other
in
zip
(
self
,
other
):
stream_port_self
.
__connect__
(
stream_port_other
)
return
Connection
(
(
self
.
component_name
,
self
.
name
),
(
other
.
component_name
,
other
.
name
)
)
def
recv
(
self
):
while
True
:
try
:
items
=
[]
for
stream_port
in
self
:
items
.
append
(
stream_port
.
pipe_end
.
recv
()
)
yield
items
except
EOFError
:
break
class
Connection
():
def
__init__
(
self
,
src
,
snk
):
self
.
src_component_name
=
src
[
0
]
self
.
src_port_name
=
src
[
1
]
self
.
snk_component_name
=
snk
[
0
]
self
.
snk_port_name
=
snk
[
1
]
self
.
vhdl_assignment_left
=
self
.
snk_component_name
+
'
_
'
+
self
.
snk_port_name
self
.
vhdl_assignment_right
=
self
.
src_component_name
+
'
_
'
+
self
.
src_port_name
self
.
vhdl_assignment_operator
=
'
<=
'
self
.
vhdl_assignment
=
self
.
vhdl_assignment_left
+
'
'
+
self
.
vhdl_assignment_operator
+
'
'
+
self
.
vhdl_assignment_right
+
'
;
\n
'
class
Component
(
mp
.
Process
):
def
__init__
(
self
,
name
,
components
=
[],
connections
=
[],
inst_nr
=
None
):
mp
.
Process
.
__init__
(
self
)
if
inst_nr
!=
None
:
self
.
name
=
name
+
'
_
'
+
str
(
inst_nr
)
else
:
self
.
name
=
name
self
.
inst_nr
=
inst_nr
self
.
file_name
=
self
.
name
+
'
.vhd
'
# Overridden by component subclasses; these assign an existing file name.
self
.
ports
=
{}
self
.
components
=
components
self
.
connections
=
connections
self
.
temp_connections
=
[]
def
start_components
(
self
):
if
self
.
components
==
[]:
# This is not a composite component but a base component, start this instance itself
self
.
start
()
else
:
# This is a composite component, start the internal instances
for
component
in
self
.
components
:
print
'
Starting
'
,
component
component
.
start_components
()
def
terminate_components
(
self
):
if
self
.
components
==
[]:
# This is not a composite component but a base component, terminate this instance itself
self
.
terminate
()
else
:
# This is a composite component, terminate the internal instances
for
component
in
self
.
components
:
print
'
Terminating
'
,
component
component
.
terminate_components
()
def
run_time
(
self
,
time_sec
):
self
.
start_components
()
time
.
sleep
(
time_sec
)
self
.
terminate_components
()
def
generate
(
self
,
target_file
=
None
):
if
self
.
components
!=
[]:
target_file
=
open
(
self
.
file_name
,
"
w
"
)
target_file
.
write
(
'
ASTRON HEADER
\n
'
)
target_file
.
write
(
'
INCLUDED LIBRARIES
\n
'
)
target_file
.
write
(
'
ENTITY DECLARATION
\n
'
)
target_file
.
write
(
'
ARCHITECTURE str OF %s IS
\n
'
%
self
.
name
)
target_file
.
write
(
'
. CONSTANT DECLARATIONS
\n
'
)
# Get the signal declaration from each internal component's port object
for
component
in
self
.
components
:
for
port_name
,
port
in
component
.
ports
.
iteritems
():
target_file
.
write
(
port
.
signal
.
vhdl_signal_declaration
)
target_file
.
write
(
'
BEGIN
\n
'
)
# Write this component's connections
for
connection
in
cm
.
flatten
(
self
.
connections
):
# print connection
target_file
.
write
(
connection
.
vhdl_assignment
)
# Iterate through internal components
for
component
in
self
.
components
:
component
.
generate
()
target_file
.
write
(
component
.
get_vhdl_instance
())
target_file
.
write
(
'
END str
\n
'
)
target_file
.
close
()
def
get_vhdl_instance
(
self
):
# Only base components have a pre-declared VHDL instance. Composites do not.
if
hasattr
(
self
,
'
vhdl_instance
'
):
# I'm a base component...return my pre-declared VHDL instace string
return
self
.
vhdl_instance
else
:
# I'm a composite component. Create a VHDL instance here.
return
'
A string that contains the %s VHDL instance
\n
'
%
self
.
name
def
__set_port__
(
self
,
name
,
mode
,
dimensions
):
"""
Mode:
.
'
in
'
.
'
out
'
Dimension examples:
. 32 = 1 stream, 32b (sosi)
. (2,32) = 2 streams, 32b each (sosi_arr)
. (2,4,32) = 2 buses, 4 streams/bus, 32b/stream (sosi_2arr)
. (8,2,4,32) = 8 buses, 2 sub-buses/bus, 4 streams/sub-bus, 32b/stream (sosi_3arr)
"""
def
__set_port__
(
self
,
name
,
mode
,
dimensions
):
if
isinstance
(
dimensions
,
int
):
# Single stream
self
.
ports
[
name
]
=
StreamPort
(
self
.
name
,
name
,
mode
,
stream_index
=
None
,
data_width
=
dimensions
)
elif
len
(
dimensions
)
==
2
:
# Multi stream
self
.
ports
[
name
]
=
StreamPortArray
(
self
.
name
,
name
,
mode
,
nof_streams
=
dimensions
[
0
],
data_width
=
dimensions
[
1
])
elif
len
(
dimensions
)
==
3
:
pass
# Multi bus, multi stream
# self.ports[name] = StreamPort2Array(self.name, name, mode, nof_buses=dimensions[0], nof_streams=dimensions[1], data_width=dimensions[2])
def
set_input
(
self
,
name
,
dimensions
):
self
.
__set_port__
(
name
=
name
,
mode
=
'
in
'
,
dimensions
=
dimensions
)
def
set_output
(
self
,
name
,
dimensions
):
self
.
__set_port__
(
name
=
name
,
mode
=
'
out
'
,
dimensions
=
dimensions
)
#'>' operator: Connect
def
__gt__
(
self
,
other
):
return
self
.
__connect__
(
other
)
def
__connect__
(
self
,
other
):
for
port_name_self
,
port_self
in
self
.
ports
.
iteritems
():
if
port_self
.
mode
==
'
out
'
:
for
port_name_other
,
port_other
in
other
.
ports
.
iteritems
():
if
port_other
.
mode
==
'
in
'
:
if
type
(
port_self
)
==
type
(
port_other
):
# We want to be able to daisy chain components so we need to store intermediate results
# in the component on the right.
connection
=
port_self
.
__connect__
(
port_other
)
other
.
temp_connections
.
append
(
connection
)
result
=
self
.
temp_connections
+
[
connection
]
self
.
temp_connections
=
[]
return
result
###############################################################################
# Component subclasses
###############################################################################
class
SingleCounter
(
Component
):
def
__init__
(
self
,
data_width
=
32
,
inst_nr
=
None
):
Component
.
__init__
(
self
,
inst_nr
=
inst_nr
,
name
=
'
SingleCounter
'
)
self
.
vhdl_instance
=
'
A string that contains the SingleCounter VHDL instance
\n
'
self
.
set_output
(
'
src_out
'
,
data_width
)
def
run
(
self
):
for
value
in
xrange
(
10
):
if
self
.
inst_nr
==
None
:
cnt_offset
=
0
else
:
cnt_offset
=
self
.
inst_nr
*
100
item
=
value
+
cnt_offset
print
'
[Counter] src
'
,
self
.
inst_nr
,
'
: sending
'
,
item
# Offset sent value by 100 for each instance number increment
self
.
ports
[
'
src_out
'
].
send
(
item
)
class
SinglePrinter
(
Component
):
def
__init__
(
self
,
data_width
=
32
,
inst_nr
=
None
):
Component
.
__init__
(
self
,
inst_nr
=
inst_nr
,
name
=
'
SinglePrinter
'
)
self
.
vhdl_instance
=
'
A string that contains the SinglePrinter VHDL instance
\n
'
self
.
set_input
(
'
snk_in
'
,
data_width
)
def
run
(
self
):
for
item
in
self
.
ports
[
'
snk_in
'
].
recv
():
print
'
[Printer] snk
'
,
self
.
inst_nr
,
'
: receiving
'
,
item
class
Counter
(
Component
):
def
__init__
(
self
,
nof_streams
,
data_width
=
32
,
inst_nr
=
None
):
Component
.
__init__
(
self
,
inst_nr
=
inst_nr
,
name
=
'
Counter
'
)
self
.
vhdl_instance
=
'
A string that contains the Counter VHDL instance
\n
'
self
.
set_output
(
'
src_out_arr
'
,
(
nof_streams
,
data_width
))
def
run
(
self
):
for
value
in
xrange
(
10
):
for
src
in
self
.
ports
[
'
src_out_arr
'
]:
item
=
value
+
src
.
stream_index
*
100
print
'
[Counter] src
'
,
src
.
stream_index
,
'
: sending
'
,
item
# Offset sent value by 100 for each incremental stream
src
.
send
(
item
)
class
Through
(
Component
):
def
__init__
(
self
,
nof_streams
,
data_width
=
32
,
inst_nr
=
None
):
Component
.
__init__
(
self
,
inst_nr
=
inst_nr
,
name
=
'
Through
'
)
self
.
vhdl_instance
=
'
A string that contains the Through VHDL instance
\n
'
self
.
set_input
(
'
snk_in_arr
'
,
(
nof_streams
,
data_width
))
self
.
set_output
(
'
src_out_arr
'
,
(
nof_streams
,
data_width
))
def
run
(
self
):
for
items
in
self
.
ports
[
'
snk_in_arr
'
].
recv
():
for
item
,
src
in
zip
(
items
,
self
.
ports
[
'
src_out_arr
'
]):
print
'
[Through] snk
'
,
src
.
stream_index
,
'
: forwarding
'
,
item
,
'
to src
'
,
src
.
stream_index
src
.
send
(
item
)
class
Printer
(
Component
):
def
__init__
(
self
,
nof_streams
,
data_width
=
32
,
inst_nr
=
None
):
Component
.
__init__
(
self
,
inst_nr
=
inst_nr
,
name
=
'
Printer
'
)
self
.
vhdl_instance
=
'
A string that contains the Printer VHDL instance
\n
'
self
.
set_input
(
'
snk_in_arr
'
,
(
nof_streams
,
data_width
))
def
run
(
self
):
for
items
in
self
.
ports
[
'
snk_in_arr
'
].
recv
():
for
item_index
,
item
in
enumerate
(
items
):
print
'
[Printer] snk
'
,
item_index
,
'
: receiving
'
,
item
###############################################################################
# Help function for keypress
###############################################################################
def
press_enter
():
try
:
input
(
"
Press enter to continue
"
)
except
SyntaxError
:
pass
###############################################################################
# Main
###############################################################################
print
print
'
###############################################################################
'
print
'
# Example 1: connect ports component-wise
'
print
'
###############################################################################
'
print
nof_streams
=
3
a
=
Counter
(
nof_streams
)
b
=
Through
(
nof_streams
)
c
=
Printer
(
nof_streams
)
connections
=
[
a
>
b
>
c
]
d
=
Component
(
'
my_component_1
'
,
[
a
,
b
,
c
],
connections
)
d
.
run_time
(
1
)
d
.
generate
()
press_enter
()
print
print
'
###############################################################################
'
print
'
# Example 2: connect ports array-wise
'
print
'
###############################################################################
'
print
nof_streams
=
3
a
=
Counter
(
nof_streams
)
b
=
Through
(
nof_streams
)
c
=
Printer
(
nof_streams
)
connections
=
[]
connections
.
append
(
a
.
ports
[
'
src_out_arr
'
]
>
b
.
ports
[
'
snk_in_arr
'
]
)
connections
.
append
(
b
.
ports
[
'
src_out_arr
'
]
>
c
.
ports
[
'
snk_in_arr
'
]
)
d
=
Component
(
'
my_component_2
'
,
[
a
,
b
,
c
],
connections
)
d
.
run_time
(
1
)
d
.
generate
()
press_enter
()
print
print
'
###############################################################################
'
print
'
# Example 3: connect ports stream-wise (with stream 0 / stream 1 swap)
'
print
'
###############################################################################
'
print
nof_streams
=
3
a
=
Counter
(
nof_streams
)
b
=
Through
(
nof_streams
)
c
=
Printer
(
nof_streams
)
connections
=
[]
connections
.
append
(
a
.
ports
[
'
src_out_arr
'
][
0
]
>
b
.
ports
[
'
snk_in_arr
'
][
0
]
)
connections
.
append
(
a
.
ports
[
'
src_out_arr
'
][
1
]
>
b
.
ports
[
'
snk_in_arr
'
][
1
]
)
connections
.
append
(
a
.
ports
[
'
src_out_arr
'
][
2
]
>
b
.
ports
[
'
snk_in_arr
'
][
2
]
)
connections
.
append
(
b
.
ports
[
'
src_out_arr
'
][
1
]
>
c
.
ports
[
'
snk_in_arr
'
][
0
]
)
# We're swapping streams 0 and 1 here
connections
.
append
(
b
.
ports
[
'
src_out_arr
'
][
0
]
>
c
.
ports
[
'
snk_in_arr
'
][
1
]
)
# We're swapping streams 0 and 1 here
connections
.
append
(
b
.
ports
[
'
src_out_arr
'
][
2
]
>
c
.
ports
[
'
snk_in_arr
'
][
2
]
)
d
=
Component
(
'
my_component_3
'
,
[
a
,
b
,
c
],
connections
)
d
.
run_time
(
1
)
d
.
generate
()
press_enter
()
print
print
'
###############################################################################
'
print
'
# Example 4: Mix single and multi stream components
'
print
'
###############################################################################
'
print
nof_streams
=
1
a
=
SingleCounter
()
b
=
Through
(
nof_streams
)
c
=
Printer
(
nof_streams
)
connections
=
[]
connections
.
append
(
a
.
ports
[
'
src_out
'
]
>
b
.
ports
[
'
snk_in_arr
'
][
0
]
)
connections
.
append
(
b
.
ports
[
'
src_out_arr
'
]
>
c
.
ports
[
'
snk_in_arr
'
]
)
d
=
Component
(
'
my_component_4
'
,
[
a
,
b
,
c
],
connections
)
d
.
run_time
(
1
)
d
.
generate
()
press_enter
()
print
print
'
###############################################################################
'
print
'
# Example 5: Creating multi-instance composites from single stream components
'
print
'
# . We replace the Counter with a new component that instantiates 3 SingeCounters
'
print
'
# . We replace the Printer with a new component that instantiates 3 SingePrinters
'
print
'
###############################################################################
'
print
nof_streams
=
3
data_width
=
32
# Create [nof_streams] SingleCounter instances
a_list
=
[]
for
i
in
range
(
nof_streams
):
a_list
.
append
(
SingleCounter
(
inst_nr
=
i
))
# Create a new components wrapping these SingleCounter instances
a_multi
=
Component
(
'
a_multi
'
,
a_list
)
# Declare the output of this new component
a_multi
.
set_output
(
'
src_out_arr
'
,
(
nof_streams
,
data_width
))
# Forward the SingleCounter outputs to the new component's output
for
i
in
range
(
nof_streams
):
a_multi
.
components
[
i
].
ports
[
'
src_out
'
]
>
a_multi
.
ports
[
'
src_out_arr
'
][
i
]
# Unchanged: the Through component
b
=
Through
(
nof_streams
)
# Create [nof_streams] SinglePrinter instances
c_list
=
[]
for
i
in
range
(
nof_streams
):
c_list
.
append
(
SinglePrinter
(
inst_nr
=
i
))
# Create a new components wrapping these SinglePrinter instances
c_multi
=
Component
(
'
c_multi
'
,
c_list
)
# Declare the input of this new component
c_multi
.
set_input
(
'
snk_in_arr
'
,
(
nof_streams
,
data_width
))
# Forward the new component's input to the SinglePrinter inputs
for
i
in
range
(
nof_streams
):
c_multi
.
ports
[
'
snk_in_arr
'
][
i
]
>
c_multi
.
components
[
i
].
ports
[
'
snk_in
'
]
# Continue as before (in the other examples)
connections
=
[
a_multi
>
b
>
c_multi
]
d
=
Component
(
'
my_component_5
'
,
[
a_multi
,
b
,
c_multi
],
connections
)
d
.
run_time
(
1
)
d
.
generate
()
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment