diff --git a/toolflow/vivado/arch/axi4mm/axi4mm.tcl b/toolflow/vivado/arch/axi4mm/axi4mm.tcl index b20a5bae..8cbbdfe4 100644 --- a/toolflow/vivado/arch/axi4mm/axi4mm.tcl +++ b/toolflow/vivado/arch/axi4mm/axi4mm.tcl @@ -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 } diff --git a/toolflow/vivado/arch/common/arch.tcl b/toolflow/vivado/arch/common/arch.tcl index 82385281..af1ab687 100644 --- a/toolflow/vivado/arch/common/arch.tcl +++ b/toolflow/vivado/arch/common/arch.tcl @@ -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 } + } diff --git a/toolflow/vivado/common/ip.tcl b/toolflow/vivado/common/ip.tcl index 5a8858c1..dccc842b 100644 --- a/toolflow/vivado/common/ip.tcl +++ b/toolflow/vivado/common/ip.tcl @@ -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"]]] \ diff --git a/toolflow/vivado/platform/common/plugins/status_core_interface.tcl b/toolflow/vivado/platform/common/plugins/status_core_interface.tcl new file mode 100644 index 00000000..a60df6fe --- /dev/null +++ b/toolflow/vivado/platform/common/plugins/status_core_interface.tcl @@ -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 . +# + +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"