Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enable PEs with multiple reg/mem slave interfaces #318

Merged
merged 6 commits into from
Mar 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions toolflow/vivado/arch/axi4mm/axi4mm.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ namespace eval arch {
set intr_name "PE_${i}_${pe_sub_interrupt}"
puts "Creating interrupt $intr_name"
connect_bd_net $pin [::tapasco::ip::add_interrupt $intr_name "design"]
incr pe_sub_interrupt
}
incr i
}
Expand Down
88 changes: 58 additions & 30 deletions toolflow/vivado/arch/common/arch.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -35,40 +35,68 @@ namespace eval arch {
set pes [lsort [get_processing_elements]]

foreach pe $pes {
puts " processing $pe registers ..."
set usrs [lsort [get_bd_addr_segs -filter { USAGE == register } $pe/*]]
for {set i 0} {$i < [llength $usrs]} {incr i} {
set seg [lindex $usrs $i]
puts " seg: $seg"
if {[get_property MODE [get_bd_intf_pins -of_objects $seg]] == "Master"} {
puts " skipping master seg $seg"
} else {
set intf [get_bd_intf_pins -of_objects $seg]
set range [get_property RANGE $seg]
set offset [next_valid_address $offset $range]
::platform::addressmap::add_processing_element [llength [dict keys $ret]] $offset $range
dict set ret $intf "interface $intf [format "offset 0x%08x range 0x%08x" $offset $range] kind register"
incr offset $range
set reg_segs [lsort [get_bd_addr_segs -filter { USAGE == register } $pe/*]]
set mem_segs [lsort [get_bd_addr_segs -filter { USAGE == memory } $pe/*]]
if {[llength $reg_segs] <= 1 && [llength $mem_segs] <= 1} {
puts " processing $pe registers ..."
for {set i 0} {$i < [llength $reg_segs]} {incr i} {
set seg [lindex $reg_segs $i]
puts " seg: $seg"
if {[get_property MODE [get_bd_intf_pins -of_objects $seg]] == "Master"} {
puts " skipping master seg $seg"
} else {
set intf [get_bd_intf_pins -of_objects $seg]
set range [get_property RANGE $seg]
set offset [next_valid_address $offset $range]
::platform::addressmap::add_processing_element [llength [dict keys $ret]] $offset $range
dict set ret $intf "interface $intf [format "offset 0x%08x range 0x%08x" $offset $range] kind register"
incr offset $range
}
}
}
puts " processing $pe memories ..."
set usrs [lsort [get_bd_addr_segs -filter { USAGE == memory } $pe/*]]
for {set i 0} {$i < [llength $usrs]} {incr i} {
set seg [lindex $usrs $i]
puts " seg: $seg"
if {[get_property MODE [get_bd_intf_pins -of_objects $seg]] == "Master"} {
puts " skipping master seg $seg"
continue
} else {
set intf [get_bd_intf_pins -of_objects $seg]
set range [get_property RANGE $seg]
set offset [next_valid_address $offset $range]
::platform::addressmap::add_processing_element [llength [dict keys $ret]] $offset $range
dict set ret $intf "interface $intf [format "offset 0x%08x range 0x%08x" $offset $range] kind memory"
incr offset $range
puts " processing $pe memories ..."
for {set i 0} {$i < [llength $mem_segs]} {incr i} {
set seg [lindex $mem_segs $i]
puts " seg: $seg"
if {[get_property MODE [get_bd_intf_pins -of_objects $seg]] == "Master"} {
puts " skipping master seg $seg"
} else {
set intf [get_bd_intf_pins -of_objects $seg]
set range [get_property RANGE $seg]
set offset [next_valid_address $offset $range]
::platform::addressmap::add_processing_element [llength [dict keys $ret]] $offset $range
dict set ret $intf "interface $intf [format "offset 0x%08x range 0x%08x" $offset $range] kind memory"
incr offset $range
}
}
} else {
# If there is more than one reg/mem interface, we add them in the same order as declared in the IP-XACT core.
# The current runtime uses the order to detect control-register-interface & memory-interface pairs.
# When a PE has multiple such interfaces, ordering them regs first, mems second leads to the runtime recognizing only one reg-memory pair.
# When using the same ordering as the IP-XACT core, the user can define which memory-interface belongs to a certain control-register-interface by ordering them accordingly.
puts " processing $pe registers and memories ..."
set all_segs [lsort [get_bd_addr_segs $pe/*]]
for {set i 0} {$i < [llength $all_segs]} {incr i} {
set seg [lindex $all_segs $i]
puts " seg: $seg"
if {[get_property MODE [get_bd_intf_pins -of_objects $seg]] == "Master"} {
puts " skipping master seg $seg"
} else {
set intf [get_bd_intf_pins -of_objects $seg]
set range [get_property RANGE $seg]
set usage [get_property USAGE $seg]
set offset [next_valid_address $offset $range]
::platform::addressmap::add_processing_element [llength [dict keys $ret]] $offset $range
if { $usage == "register" } {
dict set ret $intf "interface $intf [format "offset 0x%08x range 0x%08x" $offset $range] kind register"
} else {
dict set ret $intf "interface $intf [format "offset 0x%08x range 0x%08x" $offset $range] kind memory"
}
incr offset $range
}
}
}
}
return $ret
}

}
6 changes: 6 additions & 0 deletions toolflow/vivado/common/ip.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,12 @@ namespace eval ::tapasco::ip {
set kid [dict get [::tapasco::get_composition] $kind id]
set vlnv [dict get [::tapasco::get_composition] $kind vlnv]

set intfinfo [tapasco::call_plugins "status-core-interface" $vlnv $intf]
if { $intfinfo != {} } {
set kid [lindex $intfinfo 0]
set vlnv [lindex $intfinfo 1]
}

lappend slots [json::write object "Type" [json::write string "Kernel"] "SlotId" $slot_id "Kernel" $kid \
"Offset" [json::write string [format "0x%016x" [expr "[dict get $addr $intf "offset"] - [::platform::get_pe_base_address]"]]] \
"Size" [json::write string [format "0x%016x" [dict get $addr $intf "range"]]] \
Expand Down
37 changes: 37 additions & 0 deletions toolflow/vivado/platform/common/plugins/status_core_interface.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright (c) 2014-2020 Embedded Systems and Applications, TU Darmstadt.
#
# This file is part of TaPaSCo
# (see https://github.com/esa-tu-darmstadt/tapasco).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

namespace eval status_core_interface {

proc get_interface_info { vlnv intf } {
set intf_rename [tapasco::get_feature "IPEC"]
set intfname [lindex [split $intf /] end]
if {[dict exists $intf_rename $vlnv $intfname]} {
set kid [dict get $intf_rename $vlnv $intfname "kid"]
set kid [expr int($kid)]
set vlnv [dict get $intf_rename $vlnv $intfname "vlnv"]
puts " replaced vlnv $vlnv kid $kid"
return [list $kid $vlnv]
}
return {}
}

}

tapasco::register_plugin "platform::status_core_interface::get_interface_info" "status-core-interface"