############################################################################### # # Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # Use of the Software is limited solely to applications: # (a) running on a Xilinx device, or # (b) that interact with a Xilinx device through a bus or interconnect. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF # OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # # Except as contained in this notice, the name of the Xilinx shall not be used # in advertising or otherwise to promote the sale, use or other dealings in # this Software without prior written authorization from Xilinx. # ############################################################################### # # This file is part of Xilkernel. # # $Id: xilkernel_v2_1_0.tcl,v 1.1.2.2 2011/12/08 08:17:56 anirudh Exp $ ############################################################################### proc kernel_drc {os_handle} { set sw_proc_handle [hsi::get_sw_processor] set hw_proc_handle [hsi::get_cells -hier [common::get_property HW_INSTANCE $sw_proc_handle]] set proctype [common::get_property IP_NAME $hw_proc_handle] set compiler [common::get_property CONFIG.compiler $sw_proc_handle] # System timer frequency must be specified set systmr_spec [common::get_property CONFIG.systmr_spec $os_handle] if { $systmr_spec == "false" } { error "ERROR: Xilkernel requires some or all of the parameters in the systmr_spec category to be defined. Please configure this categry as 'true'." "" "mdt_error" } set stacksiz [common::get_property CONFIG.pthread_stack_size $os_handle] switch -regexp $proctype { "microblaze" { if { [string first "mb-gcc" $compiler] == 0 && [string first "mb-g++" $compiler] == 0} { error "ERROR: Wrong compiler requested. Xilkernel can be compiled only with the GNU compiler for MicroBlaze." "" "mdt_error" } set systmr_dev [common::get_property CONFIG.systmr_dev $os_handle] if { $systmr_dev == "none" } { error "ERROR: Xilkernel for Microblaze requires a system timer device to be specified. Please choose a valid peripheral instance in the systmr_dev parameter." "" "mdt_error" } set systmr_handle [hsi::get_cells -hier $systmr_dev] set systmr_type [common::get_property IP_NAME $systmr_handle] if { $systmr_type != "fit_timer" && $systmr_type != "opb_timer" && $systmr_type != "xps_timer" && $systmr_type != "axi_timer" } { error "ERROR: Xilkernel for Microblaze can work only with an axi_timer, xps_timer, opb_timer or fit_timer. Please choose a valid device as the system timer with the parameter systmr_dev." "" "mdt_error" } if { [expr $stacksiz % 4] != 0 } { error "ERROR: pthread_stack_size must be a multiple of 4." } set procver [common::get_property CONFIG.HW_VER $hw_proc_handle] } ppc* { if { $compiler != "powerpc-eabi-gcc" && $compiler != "powerpc-eabi-g++" } { error "ERROR: Wrong compiler requested. Xilkernel can be compiled only with the GNU compiler for PPC." "" "mdt_error" } if { [expr $stacksiz % 8] != 0 } { error "ERROR: pthread_stack_size must be a multiple of 8." } } "default" { error "ERROR: Unsupported processor type: $proctype. Xilkernel supported only for PPC and Microblaze." "" "mdt_error" } } set systmr_freq [common::get_property CONFIG.systmr_freq $os_handle] if { $systmr_freq == -1 } { error "ERROR: System timer frequency not specified." "" "mdt_error" } set systmr_interval_ms [common::get_property CONFIG.systmr_interval $os_handle] if { $systmr_interval_ms <= 0 } { error "ERROR: Invalid value for parameter systmr_interval specified. Please specify a positive value." "" "mdt_error" } set config_bufmalloc [common::get_property CONFIG.config_bufmalloc $os_handle] if { $config_bufmalloc == "true" } { set memtable_handle [hsi::get_arrays mem_table -of_objects $os_handle] #set memtable_elements [xget_handle $memtable_handle "ELEMENTS" "*"] set memtable_elements [llength [common::get_property PARAM.mem_nblks $memtable_handle]] foreach ele $memtable_elements { set bsiz [common::get_property PARAM.mem_bsize $memtable_handle] set nblks [common::get_property PARAM.mem_nblks $memtable_handle] if { $bsiz < 4 } { error "ERROR: mem_table mem_bsize specification of $bsiz is incorrect. Block size should be >= 4." "" "mdt_error" } if { $nblks <= 0 } { error "ERROR: mem_table mem_nblks specification of $nblks is incorrect. Block count should be positive." "" "mdt_error" } } } set config_msgq [common::get_property CONFIG.config_msgq $os_handle] if { $config_msgq == "true" } { set use_malloc [common::get_property CONFIG.use_malloc $os_handle] if { $use_malloc != "true" && $config_bufmalloc != "true" } { error "ERROR: Message queues require memory allocation support. Please configure parameters config_bufmalloc or use_malloc to be true." "" "mdt_error" } } } proc generate {os_handle} { variable standalone_version set sw_proc_handle [hsi::get_sw_processor] set hw_proc_handle [hsi::get_cells -hier [common::get_property HW_INSTANCE $sw_proc_handle]] set proctype [common::get_property IP_NAME $hw_proc_handle] set procver [common::get_property CONFIG.HW_VER $hw_proc_handle] set need_config_file "false" # proctype should be "microblaze" set mbsrcdir "../standalone/src/microblaze" set ppcsrcdir "../standalone/src/ppc405" set ppc440srcdir "../standalone/src/ppc440" set commondir "../standalone/src/common" set datadir "../standalone/data" foreach entry [glob -nocomplain [file join $commondir *]] { file copy -force $entry [file join ".." "standalone" "src"] } # proctype should be "microblaze" switch -regexp $proctype { "microblaze" { file copy -force "./src/Makefile_mb.sh" "./src/Makefile" foreach entry [glob -nocomplain [file join $mbsrcdir *]] { if { [string first "hw_exception_handler" $entry] == -1 } { ;# Do not copy over the Standalone BSP exception handler file copy -force $entry [file join ".." "standalone" "src"] } } file rename -force -- "../standalone/src/Makefile" "../standalone/src/Makefile_depends" set need_config_file "true" } ppc* { file copy -force "./src/Makefile_ppc.sh" "./src/Makefile" # Write the arch.make file set makecpu [open "./src/cpu.make" w] ::hsi::utils::write_tcl_header $makecpu "Configuration parameters for PPC Xilkernel Makefile" if { [string match -nocase ppc440* $proctype] } { puts $makecpu "CPU_TYPE=440" } else { puts $makecpu "CPU_TYPE=405" } close $makecpu if { [string match -nocase ppc440* $proctype] } { set ppcsrcdir $ppc440srcdir } foreach entry [glob -nocomplain [file join $ppcsrcdir *]] { if { [string first "xvectors" $entry] == -1 } { ;# Do not copy xvectors.S. Xilkernel provides its own. file copy -force $entry [file join ".." "standalone" "src"] } } } "default" {puts "unknown processor type $proctype\n"} } # Write the config.make file set makeconfig [open "../standalone/src/config.make" w] #::hsi::utils::write_tcl_header $makeconfig "Configuration parameters for Standalone Makefile" if { $proctype == "microblaze" } { if { [mb_has_exceptions $hw_proc_handle] } { puts $makeconfig "LIBSOURCES = *.c *.S" } else { puts $makeconfig "LIBSOURCES = *.s *.c" } } puts $makeconfig "LIBS = standalone_libs" close $makeconfig # Remove microblaze directories... file delete -force $mbsrcdir file delete -force $ppcsrcdir file delete -force $datadir # Handle stdin and stdout ::hsi::utils::handle_stdin $os_handle ::hsi::utils::handle_stdout $os_handle # Modify Makefile based on whether inbyte.c and outbyte.c been created if {[file exists "./src/inbyte.c"] && [file exists "./src/inbyte.c"]} { set source [open "./src/Makefile" r] set destination [open Makefile.txt w] set contents [read $source] close $source set lines [split $contents \n] foreach line $lines { if {[regexp -- "standalone:" $line]} { puts $destination "standalone:" puts $destination "\t\$(CC) \$(CFLAGS) -c \$(INCLUDES) \$(STANDALONE_STDIN_SRC)" puts $destination "\t\$(AR) -r \$(LIBDIR)/\$(LIBXIL) \$(STANDALONE_STDIN_OBJ)" puts $destination "\t\$(CC) \$(CFLAGS) -c \$(INCLUDES) \$(STANDALONE_STDOUT_SRC)" puts $destination "\t\$(AR) -r \$(LIBDIR)/\$(LIBXIL) \$(STANDALONE_STDOUT_OBJ)" } else { puts $destination $line } } close $destination file delete "./src/Makefile" file rename Makefile.txt "./src/Makefile" } # Create config file for microblaze interrupt handling if {[string compare -nocase $need_config_file "true"] == 0} { xhandle_mb_interrupts } # Create config files for Microblaze exception handling if { $proctype == "microblaze" && [mb_has_exceptions $hw_proc_handle] } { xcreate_mb_exc_config_file } # Create bspconfig file set bspcfg_fn [file join ".." "standalone" "src" "bspconfig.h"] file delete $bspcfg_fn set bspcfg_fh [open $bspcfg_fn w] ::hsi::utils::write_c_header $bspcfg_fh "Configurations for Standalone BSP" if { $proctype == "microblaze" && [mb_has_pvr $hw_proc_handle] } { set pvr [common::get_property CONFIG.C_PVR $hw_proc_handle] switch $pvr { "0" { puts $bspcfg_fh "#define MICROBLAZE_PVR_NONE" } "1" { puts $bspcfg_fh "#define MICROBLAZE_PVR_BASIC" } "2" { puts $bspcfg_fh "#define MICROBLAZE_PVR_FULL" } "default" { puts $bspcfg_fh "#define MICROBLAZE_PVR_NONE" } } } close $bspcfg_fh set config_file [xopen_new_include_file "./src/include/os_config.h" "XilKernel Configuration parameters"] set init_file [xopen_new_include_file "./src/include/config/config_init.h" "XilKernel Configuration parameters"] ::hsi::utils::write_c_header $init_file "LibXilKernel Initialization structures" puts $init_file "\#include " puts $init_file "\#include \n\n" switch -regexp $proctype { "microblaze" { xput_define $config_file "MB_XILKERNEL" "" if {[mb_has_exceptions $hw_proc_handle] } { xput_define $config_file "CONFIG_HARDWARE_EXCEPTIONS" "" } if {[mb_has_exceptions $hw_proc_handle] } { xput_define $config_file "CONFIG_HARDWARE_EXCEPTIONS" "" } set base_vectors_handle [common::get_property CONFIG.C_BASE_VECTORS $hw_proc_handle] if { $base_vectors_handle != "" } { set base_vectors [common::get_property CONFIG.C_BASE_VECTORS $hw_proc_handle] } else { set base_vectors 0x00000000 } xput_define $config_file "CONFIG_BASE_VECTORS" "$base_vectors" } ppc* { xput_define $config_file "PPC_XILKERNEL" "" if { [string match -nocase ppc440* $proctype] } { xput_define $config_file "PPC_CPU_440" "" } } } # Create defines and struct initializations set config_debug_support [common::get_property CONFIG.config_debug_support $os_handle] if { $config_debug_support == "true" } { set config_debug_mode [common::get_property CONFIG.verbose $os_handle] if { $config_debug_mode == "true" } { xadd_define $config_file $os_handle "verbose" } ;# set config_debug_mon [xget_value $os_handle "PARAMETER" "debug_mon"] ;# if { $config_debug_mon == "true" } { ;# xadd_define $config_file $os_handle "config_debugmon" ;# } } set config_enhanced_features [common::get_property CONFIG.enhanced_features $os_handle] if { $config_enhanced_features == "true" } { set config_kill [common::get_property CONFIG.config_kill $os_handle] if { $config_kill == "true" } { xadd_define $config_file $os_handle "config_kill" } set config_yield [common::get_property CONFIG.config_yield $os_handle] if { $config_yield == "true" } { xadd_define $config_file $os_handle "config_yield" } } set config_elf_process [common::get_property CONFIG.config_elf_process $os_handle] if { $config_elf_process == "true" } { xadd_define $config_file $os_handle "config_elf_process" xadd_define $config_file $os_handle "max_procs" # Get the Entry Point address, priority for static ELF processes table set static_elf_process_table_handle [hsi::get_arrays -of_objects $os_handle "static_elf_process_table"] if { $static_elf_process_table_handle != "" } { #SRI FIX THIS set n_init_process [common::get_property SIZE $static_elf_process_table_handle] xput_define $config_file "n_init_process" $n_init_process xadd_define $config_file $os_handle "config_static_elf_process_support" xadd_struct $init_file $os_handle "_process_init" "se_process_table" "static_elf_process_table" "process_start_addr" "process_prio" } } set config_pthread [common::get_property CONFIG.config_pthread_support $os_handle] if { $config_pthread == "true" } { xadd_define $config_file $os_handle "config_pthread_support" xadd_define $config_file $os_handle "max_pthreads" xadd_define $config_file $os_handle "pthread_stack_size" set static_pthread_table_handle [hsi::get_arrays static_pthread_table -of_objects $os_handle] if { $static_pthread_table_handle != "" } { #set n_init_self_pthreads [llength $static_pthread_table_handle] set n_init_self_pthreads [llength [common::get_property PARAM.pthread_prio [hsi::get_arrays $static_pthread_table_handle -of_objects $os_handle]]] #set n_init_self_pthreads [common::get_property CONFIG.static_pthread_table $os_handle] if {$n_init_self_pthreads != "" } { xput_define $config_file "config_static_pthread_support" "true" xput_define $config_file "n_init_self_pthreads" $n_init_self_pthreads xadd_extern_fname $init_file $os_handle "static_pthread_table" "pthread_start_func" xadd_struct $init_file $os_handle "_elf_pthread_init" "kb_pthread_table" "static_pthread_table" "pthread_start_func" "pthread_prio" } } set config_pthread_mutex [common::get_property CONFIG.config_pthread_mutex $os_handle] if { $config_pthread_mutex == "true" } { xadd_define $config_file $os_handle "config_pthread_mutex" xadd_define $config_file $os_handle "max_pthread_mutex" set max_pthread_mutex_waitq [common::get_property CONFIG.max_pthread_mutex_waitq $os_handle] xput_define $config_file "max_pthread_mutex_waitq" $max_pthread_mutex_waitq } } # System timer configuration (Microblaze only. kernel DRC ensures this) set systmr_spec [common::get_property CONFIG.systmr_spec $os_handle] if { $proctype == "microblaze" } { set systmr_dev [common::get_property CONFIG.systmr_dev $os_handle] set systmr_handle [hsi::get_cells -hier $systmr_dev] set systmr_type [common::get_property IP_NAME $systmr_handle] } if { $proctype == "microblaze" } { if { $systmr_type == "opb_timer" || $systmr_type == "xps_timer" || $systmr_type == "axi_timer"} { xput_define $config_file "CONFIG_TIMER_PIT" "true" set systmr_baseaddr [common::get_property CONFIG.C_BASEADDR $systmr_handle] xput_define $config_file "systmr_baseaddr" $systmr_baseaddr } } set systmr_freq [common::get_property CONFIG.systmr_freq $os_handle] if { $proctype == "ppc405" || $proctype == "ppc405_virtex4" || $proctype == "ppc440_virtex5" } { set systmr_interval_ms [common::get_property CONFIG.systmr_interval $os_handle] set systmr_interval [expr [expr double($systmr_freq) * double($systmr_interval_ms)] / 1000] set systmr_interval [expr int($systmr_interval)] } elseif {$proctype == "microblaze" && [expr {$systmr_type == "opb_timer" || $systmr_type == "xps_timer" || $systmr_type == "axi_timer"}]} { set systmr_interval_ms [common::get_property CONFIG.systmr_interval $os_handle] set systmr_interval [expr [expr double($systmr_freq) * double($systmr_interval_ms)] / 1000] set systmr_interval [expr int($systmr_interval)] } elseif { $proctype == "microblaze" && $systmr_type == "fit_timer" } { set systmr_interval [common::get_property CONFIG.C_NO_CLOCKS $systmr_handle] } xput_define $config_file "SYSTMR_INTERVAL" $systmr_interval xput_define $config_file "SYSTMR_CLK_FREQ" $systmr_freq xput_define $config_file "SYSTMR_CLK_FREQ_KHZ" [expr $systmr_freq / 1000] # Interrupt controller configuration set sysintc_spec [common::get_property CONFIG.sysintc_spec $os_handle] if { $sysintc_spec != "none" } { xput_define $config_file "CONFIG_INTC" "true" set sysintc_dev_handle [hsi::get_cells -hier $sysintc_spec] set sysintc_baseaddr [::hsi::utils::get_ip_param_name $sysintc_dev_handle "C_BASEADDR"] set sysintc_device_id [::hsi::utils::get_ip_param_name $sysintc_dev_handle "DEVICE_ID"] xput_define $config_file "sysintc_baseaddr" $sysintc_baseaddr xput_define $config_file "sysintc_device_id" $sysintc_device_id # Additionally for microblaze, figure out which interrupt # input is the system timer interrupt and define its ID if { $proctype == "microblaze" } { set systmr_intr [hsi::get_pins -of_objects [hsi::get_cells -hier $systmr_handle] Interrupt] #set systmr_intr [xget_value $systmr_handle "PORT" "Interrupt"] if { [string compare -nocase $systmr_intr ""] == 0 } { error "ERROR: System Timer Interrupt PORT is not specified" "" "mdt_error" } #set mhs_handle [hsi::get_cells -of_object $systmr_handle] set intr_ports [::hsi::utils::get_sink_pins [hsi::get_pins -of_objects [hsi::get_cells -hier $systmr_intr] INTERRUPT]] #set intr_ports [xget_connected_ports_handle $mhs_handle $systmr_intr "sink"] foreach intr_port $intr_ports { set intr_port_type [common::get_property TYPE $intr_port] if { [string compare -nocase $intr_port_type "global"] == 0 } { continue } set intc_handle [hsi::get_cells -of_object $intr_port] set intc_name [common::get_property NAME $intc_handle] set proc_intc_handle [hsi::get_cells -hier $intc_name] if { [string compare -nocase $sysintc_dev_handle $intc_handle] == 0 } { continue } set systmr_intrpin [hsi::get_pins -of_objects [hsi::get_cells -hier $systmr_handle] -filter "TYPE == INTERRUPT"] set intr_id [::hsi::utils::get_port_intr_id $systmr_handle $systmr_intrpin] puts $config_file "#define SYSTMR_INTR_ID $intr_id\n" } } } set config_sched [common::get_property CONFIG.config_sched $os_handle] if { $config_sched == "true" } { xadd_define $config_file $os_handle "config_sched" xadd_define $config_file $os_handle "sched_type" xadd_define $config_file $os_handle "n_prio" set sched_type [common::get_property CONFIG.sched_type $os_handle] if { $sched_type == "SCHED_PRIO" } { xput_define $config_file "config_priosched" "true" } else { xput_define $config_file "config_rrsched" "true" } xadd_define $config_file $os_handle "max_readyq" } set config_sema [common::get_property CONFIG.config_sema $os_handle] if { $config_sema == "true" } { xadd_define $config_file $os_handle "config_sema" xadd_define $config_file $os_handle "max_sem" xadd_define $config_file $os_handle "max_sem_waitq" set config_named_sema [common::get_property CONFIG.config_named_sema $os_handle] if { $config_named_sema == "true" } { xadd_define $config_file $os_handle "config_named_sema" } } set config_msgq [common::get_property CONFIG.config_msgq $os_handle] if { $config_msgq == "true" } { set num_msgqs [common::get_property CONFIG.num_msgqs $os_handle] set msgq_capacity [common::get_property CONFIG.msgq_capacity $os_handle] set use_malloc [common::get_property CONFIG.use_malloc $os_handle] xadd_define $config_file $os_handle "config_msgq" xadd_define $config_file $os_handle "num_msgqs" xadd_define $config_file $os_handle "msgq_capacity" if { $use_malloc == "true" } { xput_define $config_file "config_enhanced_msgq" "true" xput_define $config_file "use_malloc" "true" } } set config_shm [common::get_property CONFIG.config_shm $os_handle] if { $config_shm == "true" } { xadd_define $config_file $os_handle "config_shm" set shm_handle [hsi::get_arrays -of_objects $os_handle "shm_table"] if { $shm_handle == "" } { error "ERROR: SHM configuration needs shm_table specification." "" "mdt_error" } set n_shm [llength [hsi::get_arrays $shm_handle -of_objects $os_handle]] xput_define $config_file "n_shm" $n_shm set shm_msize [get_field_sum $os_handle "shm_table" "shm_size"] xput_define $config_file "shm_msize" $shm_msize xadd_struct $init_file $os_handle "_shm_init" "shm_config" "shm_table" "shm_size" } set config_bufmalloc [common::get_property CONFIG.config_bufmalloc $os_handle] if { $config_bufmalloc == "true" } { xadd_define $config_file $os_handle "config_bufmalloc" #set memtable_handle [xget_handle $os_handle "ARRAY" "mem_table"] set memtable_elements [hsi::get_arrays -of_objects $os_handle "mem_table"] set n_static_bufs [llength $memtable_elements] set max_bufs [common::get_property CONFIG.max_bufs $os_handle] set bufmalloc_msize [get_field_product_sum $os_handle "mem_table" "mem_bsize" "mem_nblks"] xput_define $config_file "bufmalloc_msize" $bufmalloc_msize xput_define $config_file "n_mbufs" [expr $max_bufs + $n_static_bufs] xput_define $config_file "n_static_bufs" $n_static_bufs xadd_struct $init_file $os_handle "bufmalloc_init_s" "bufmalloc_cfg" "mem_table" "mem_bsize" "mem_nblks" } set config_time [common::get_property CONFIG.config_time $os_handle] if { $config_time == "true" } { xadd_define $config_file $os_handle "config_time" xadd_define $config_file $os_handle "max_tmrs" } #set config_stats [xget_value $os_handle "PARAMETER" "config_stats"] #if { $config_stats == "true" } { # xadd_define $config_file $os_handle "config_stats" #} # Handle I/O ranges for MicroBlaze MPU here if { $proctype == "microblaze" } { #set mhs_handle [hsi::get_cells -of_object $hw_proc_handle] set mmu [common::get_property CONFIG.C_USE_MMU $hw_proc_handle] if { $mmu >= 2 } { # Enumerate all the I/O ranges into a structure set interconnect [common::get_property CONFIG.C_INTERCONNECT $hw_proc_handle] if { $interconnect == "" || $interconnect == 0 } { set dbus_if_name "DOPB" } elseif { $interconnect == 1 } { set dbus_if_name "DPLB" } else { set dbus_if_name "M_AXI_DP" } set dbus_name [::hsi::utils::get_intfnet_name $hw_proc_handle $dbus_if_name] set dbus_handle [hsi::get_cells -hier $dbus_name] if { $interconnect == 2 } { set dcachelink_handle [hsi::get_cells -hier "DXCL"] } else { set dcachelink_handle [hsi::get_cells -hier "M_AXI_DC"] } #set addrlist [xget_hw_bus_slave_addrpairs $dbus_handle] set addrlists [hsi::get_mem_ranges -of_objects [hsi::get_cells -hier $sw_proc_handle]] set addrlist [list] foreach addrist $addrlists { set ip_name [common::get_property IP_NAME [hsi::get_cells -hier $addrist]] if { $ip_name == "axi_emc" || $ip_name == "mig_7series" } { set mem [lindex [hsi::get_mem_ranges $addrist] 0] set mc_base [common::get_property BASE_VALUE $mem] set mc_high [common::get_property HIGH_VALUE $mem] lappend addrlist $mc_base $mc_high } else { set mem [hsi::utils::get_ip_mem_ranges $addrist] set mc_base [common::get_property BASE_VALUE $mem] set mc_high [common::get_property HIGH_VALUE $mem] lappend addrlist $mc_base $mc_high } } if { $dcachelink_handle != "" } { #set xcl_addrlist [xget_hw_bus_slave_addrpairs $dcachelink_handle] set xcl_addrlist [hsi::get_mem_ranges -of_objects [hsi::get_cells -hier $sw_proc_handle]] set addrlist [concat addrlist xcl_addrlist] } set io_addrlist [list] # Get the list of memory controllers in the mhs. We want to filter # "memories" from the above addrlist set memcon_handles [xget_memory_controller_handles [hsi::get_cells -hier $sw_proc_handle]] #set memcon_handles [hsi::get_mem_ranges -of_objects [hsi::get_cells -hier $sw_proc_handle]] set n_ioranges 0 foreach {base high} $addrlist { set skip 0 foreach {memcon_handle} $memcon_handles { set memcon_addrlist [::hsi::utils::get_ip_mem_ranges $memcon_handle] foreach mem_range $memcon_addrlist { set mc_base [common::get_property BASE_VALUE $mem_range] set mc_high [common::get_property HIGH_VALUE $mem_range] if {$mc_base == $base && $mc_high == $high} { set skip 1 } } } if { $skip == 0 } { # Don't add duplicates set io_skip 0 foreach {io_base io_high} $io_addrlist { if { $io_base == $base && $io_high == $high } { set io_skip 1 } } if { $io_skip == 0 } { lappend io_addrlist $base $high incr n_ioranges } } } puts $config_file "#define XILKERNEL_IO_NRANGES $n_ioranges" puts $init_file "xilkernel_io_range_t system_io_range\[XILKERNEL_IO_NRANGES\] = \{" set count 0 foreach {base high} $io_addrlist { set base [format "0x%X" $base] set high [format "0x%X" $high] incr count puts -nonewline $init_file "\t\{$base, $high, MPU_PROT_READWRITE" if {$count < $n_ioranges} { puts $init_file "\}," } else { puts $init_file "\}" } } puts $init_file "\}\;" } } # complete the header protectors puts $config_file "\#endif" close $config_file puts $init_file "\#endif" close $init_file } proc xopen_new_include_file { filename description } { set inc_file [open $filename w] ::hsi::utils::write_c_header $inc_file $description set newfname [string map {. _} [lindex [split $filename {\/}] end]] puts $inc_file "\#ifndef _[string toupper $newfname]" puts $inc_file "\#define _[string toupper $newfname]\n\n" return $inc_file } proc xadd_define { config_file os_handle parameter } { set param_value [common::get_property CONFIG.$parameter $os_handle] puts $config_file "#define [string toupper $parameter] $param_value\n" # puts "creating #define [string toupper $parameter] $param_value\n" } proc xput_define { config_file parameter param_value } { puts $config_file "#define [string toupper $parameter] $param_value\n" # puts "creating #define [string toupper $parameter] $param_value\n" } # args field of the array proc xadd_extern_fname {initfile oshandle arrayname arg} { set arrahandle [hsi::get_arrays $arrayname -of_objects $oshandle] set elements [llength [common::get_property PARAM.$arg $arrahandle]] foreach ele $elements { set thread_names [common::get_property PARAM.$arg $arrahandle] foreach thread_name $thread_names { puts $initfile "extern void $thread_name\(void\)\;" } } puts $initfile "" } # args is variable no - fields of the array proc xadd_struct {initfile oshandle structtype structname arrayname args} { #set arrhandle [hsi::get_arrays $arrayname -of_objects $oshandle] set arrhandle [hsi::get_arrays $arrayname -of_objects $oshandle] foreach arg $args { set max_count [llength [common::get_property PARAM.$arg $arrhandle]] } #set elements [xget_handle $arrhandle "ELEMENTS" "*"] set count 0 #set max_count [llength $elements] set num_list "" set name_list "" set index 0 puts $initfile "struct $structtype $structname\[$max_count\] = \{" foreach arg $args { set field_values [common::get_property PARAM.$arg $arrhandle] set field_value [list] if {$index == 0} { set name_list $field_values } else { set num_list $field_values } incr index } for {set i 0} {$i < [llength $name_list]} {incr i} { incr count puts -nonewline $initfile "\t\{" puts -nonewline $initfile "[lindex $name_list $i]" if {$num_list != ""} { puts -nonewline $initfile "," puts -nonewline $initfile "[lindex $num_list $i]" } if {$count < $max_count} { puts $initfile "\}," } else { puts $initfile "\}" } } puts $initfile "\}\;" } # return the sum of all the arg field values in arrayname proc get_field_sum {oshandle arrayname arg} { #set arrhandle [hsi::get_arrays -of_objects $oshandle $arrayname] set elements [hsi::get_arrays -of_objects $oshandle $arrayname] #set elements [xget_handle $arrhandle "ELEMENTS" "*"] set count 0 set max_count [llength $elements] foreach ele $elements { set field_value [common::get_property CONFIG.$arg $ele] set count [expr $field_value+$count] } return $count } # return the sum of the product of field values in arrayname proc get_field_product_sum {oshandle arrayname field1 field2} { #set arrhandle [hsi::get_arrays -of_objects $oshandle $arrayname] set elements [hsi::get_arrays -of_objects $oshandle $arrayname] #set elements [xget_handle $arrhandle "ELEMENTS" "*"] set count 0 set max_count [llength $elements] set field1_list "" set field2_list "" foreach ele $elements { #set field_value [common::get_property PARAM.$field $ele] set field1_value [common::get_property PARAM.$field1 $ele] set field1_list $field1_value set field2_value [common::get_property PARAM.$field2 $ele] set field2_list $field2_value } for {set i 0} {$i < [llength $field1_value]} {incr i} { set field1_valuee [lindex $field1_list $i] set field2_valuee [lindex $field2_list $i] set incr_value [expr $field1_valuee*$field2_valuee] set count [expr $count+$incr_value] } return $count } proc xhandle_mb_interrupts {} { set default_interrupt_handler "XNullHandler" set default_arg "XNULL" set source_interrupt_handler $default_interrupt_handler set source_handler_arg $default_arg # Handle the interrupt pin set sw_proc_handle [hsi::get_sw_processor] set periph [hsi::get_cells -hier [common::get_property HW_INSTANCE $sw_proc_handle]] set source_ports [::hsi::utils::get_interrupt_sources $periph] if {[llength $source_ports] > 1} { error "ERROR: Too many interrupting ports on the MicroBlaze. Should only find 1" "" "hsi_error" return } if {[llength $source_ports] == 1} { set source_port [lindex $source_ports 0] if {[llength $source_port] != 0} { set source_port_name [common::get_property NAME $source_port] set source_periph [hsi::get_cells -of_object $source_port] set source_name [common::get_property NAME $source_periph] set source_driver [hsi::get_drivers $source_name] if {[string compare -nocase $source_driver ""] != 0} { #set int_array [hsi::get_arrays interrupt_handler -of_objects $source_driver] set int_array_elems [hsi::get_arrays interrupt_handler -of_objects $source_driver] #if {[llength $int_array] != 0} { #set int_array_elems [xget_handle $int_array "ELEMENTS" "*"] if {[llength $int_array_elems] != 0} { foreach int_array_elem $int_array_elems { set int_port [common::get_property CONFIG.int_port $int_array_elem] if {[llength $int_port] != 0} { if {[string compare -nocase $int_port $source_port_name] == 0 } { set source_interrupt_handler [common::get_property CONFIG.int_handler $int_array_elem] set source_handler_arg [common::get_property CONFIG.int_handler_arg $int_array_elem] if {[string compare -nocase $source_handler_arg DEVICE_ID] == 0 } { set source_handler_arg [::hsi::utils::get_ip_param_name $source_periph "DEVICE_ID"] } else { if {[string compare -nocase "global" [common::get_property TYPE $source_port]] == 0} { set source_handler_arg $default_arg } else { set source_handler_arg [::hsi::utils::get_ip_param_name $source_periph "C_BASEADDR"] } } break } } } } #} } } } # Generate microblaze_interrupts_g.c file... xcreate_mb_intr_config_file $source_interrupt_handler $source_handler_arg } proc xcreate_mb_intr_config_file {handler arg} { variable standalone_version set mb_table "MB_InterruptVectorTable" set filename [file join "../standalone/src" "microblaze_interrupts_g.c"] file delete $filename set config_file [open $filename w] ::hsi::utils::write_c_header $config_file "Interrupt Handler Table for MicroBlaze Processor" puts $config_file "#include \"microblaze_interrupts_i.h\"" puts $config_file "#include \"xparameters.h\"" puts $config_file "\n" puts $config_file [format "extern void %s (void *);" $handler] puts $config_file "\n/*" puts $config_file "* The interrupt handler table for microblaze processor" puts $config_file "*/\n" puts $config_file [format "%sEntry %s\[\] =" $mb_table $mb_table] puts $config_file "\{" puts -nonewline $config_file [format "\{\t%s" $handler] puts -nonewline $config_file [format ",\n\t(void*) %s\}" $arg] puts -nonewline $config_file "\n\};" puts $config_file "\n" close $config_file } # ------------------------------------------- # Tcl procedure xcreate_mb_exc_config file # ------------------------------------------- proc xcreate_mb_exc_config_file { } { set hfilename [file join "src" "include" "microblaze_exceptions_g.h"] file delete $hfilename set hconfig_file [open $hfilename w] ::hsi::utils::write_c_header $hconfig_file "Exception Handling Header for MicroBlaze Processor" puts $hconfig_file "\n" set sw_proc_handle [hsi::get_sw_processor] set hw_proc_handle [hsi::get_cells -hier [common::get_property HW_INSTANCE $sw_proc_handle]] set procver [common::get_property CONFIG.HW_VER $hw_proc_handle] if { ![mb_has_exceptions $hw_proc_handle]} { ;# NO exceptions are enabled close $hconfig_file ;# Do not generate any info in either the header or the C file return } puts $hconfig_file "\#define MICROBLAZE_EXCEPTIONS_ENABLED 1" if { [mb_can_handle_exceptions_in_delay_slots $procver] } { puts $hconfig_file "#define MICROBLAZE_CAN_HANDLE_EXCEPTIONS_IN_DELAY_SLOTS" } close $hconfig_file } # -------------------------------------- # Tcl procedure post_generate # This proc removes from libxil.a the basic # and standalone BSP versions of # _interrupt_handler and _hw_exception_handler # routines # -------------------------------------- proc post_generate {os_handle} { set sw_proc_handle [hsi::get_sw_processor] set hw_proc_handle [hsi::get_cells -hier [common::get_property HW_INSTANCE $sw_proc_handle]] set proctype [common::get_property IP_NAME $hw_proc_handle] set procname [common::get_property NAME $hw_proc_handle] set procdrv [hsi::get_sw_processor] set archiver [common::get_property CONFIG.archiver $procdrv] if {[string compare -nocase $proctype "microblaze"] == 0 } { # Remove _interrupt_handler.o from libxil.a for Xilkernel set libgloss_a [file join .. .. lib libgloss.a] if { ![file exists $libgloss_a] } { set libgloss_a [file join .. .. lib libxil.a] } exec $archiver -d $libgloss_a _interrupt_handler.o # We have linkage problems due to how these platforms are defined. Can't do this right now. # # Remove _exception_handler.o from libxil.a for Xilkernel # exec bash -c "$archiver -d ../../lib/libxil.a _exception_handler.o" # Remove _hw_exception_handler.o from libxil.a for microblaze cores with exception support # if {[mb_has_exceptions $hw_proc_handle]} { # exec bash -c "$archiver -d ../../lib/libxil.a _hw_exception_handler.o" # } } } # -------------------------------------- # Return true if this MB has # exception handling support # -------------------------------------- proc mb_has_exceptions { hw_proc_handle } { # Check if the following parameters exist on this MicroBlaze's MPD set ee [common::get_property CONFIG.C_UNALIGNED_EXCEPTIONS $hw_proc_handle] if { $ee != "" } { return true } set ee [common::get_property CONFIG.C_ILL_OPCODE_EXCEPTION $hw_proc_handle] if { $ee != "" } { return true } set ee [common::get_property CONFIG.C_IOPB_BUS_EXCEPTION $hw_proc_handle] if { $ee != "" } { return true } set ee [common::get_property CONFIG.C_DOPB_BUS_EXCEPTION $hw_proc_handle] if { $ee != "" } { return true } set ee [common::get_property CONFIG.C_DIV_BY_ZERO_EXCEPTION $hw_proc_handle] if { $ee != "" } { return true } set ee [common::get_property CONFIG.C_DIV_ZERO_EXCEPTION $hw_proc_handle] if { $ee != "" } { return true } set ee [common::get_property CONFIG.C_FPU_EXCEPTION $hw_proc_handle] if { $ee != "" } { return true } set ee [common::get_property CONFIG.C_USE_MMU $hw_proc_handle] if { $ee != "" && $ee != 0 } { return true } return false } # -------------------------------------- # Return true if this MB has # FPU exception handling support # -------------------------------------- proc mb_has_fpu_exceptions { hw_proc_handle } { # Check if the following parameters exist on this MicroBlaze's MPD set ee [common::get_property CONFIG.C_FPU_EXCEPTION $hw_proc_handle] if { $ee != "" } { return true } return false } # -------------------------------------- # Return true if this MB has PVR support # -------------------------------------- proc mb_has_pvr { hw_proc_handle } { # Check if the following parameters exist on this MicroBlaze's MPD set pvr [common::get_property CONFIG.C_PVR $hw_proc_handle] if { $pvr != "" } { return true } return false } # -------------------------------------- # Return true if MB ver 'procver' has # support for handling exceptions in # delay slots # -------------------------------------- proc mb_can_handle_exceptions_in_delay_slots { procver } { if { [string compare -nocase $procver "5.00.a"] >= 0 } { return true } else { return false } } # -------------------------------------------------------------------------- # Gets all the handles that are memory controller cores. # -------------------------------------------------------------------------- proc xget_memory_controller_handles { mhs } { set ret_list "" # Gets all MhsInsts in the system set mhsinsts [hsi::get_cells -hier *] # Loop thru each MhsInst and determine if have "ADDR_TYPE = MEMORY" in # the parameters. foreach mhsinst $mhsinsts { # Gets all parameters of the component set mem_ranges [::hsi::utils::get_ip_mem_ranges $mhsinst] # Loop thru each param and find tag "ADDR_TYPE = MEMORY" foreach mem_range $mem_ranges { if {$mem_range == ""} { continue } #set addrTypeValue [xget_hw_subproperty_value $param "ADDR_TYPE" ] if {[string compare -nocase [common::get_property MEM_TYPE $mem_range ] MEMORY] == 0} { lappend ret_list $mhsinst break; } } } return $ret_list }