Advertisement
Guest User

Untitled

a guest
Jun 5th, 2025
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
TCL 12.70 KB | Source Code | 0 0
  1. ######################################################################
  2. # Automatically inserts ILA instances in a batch flow, and calls "implement_debug_core".   Can also be used in a GUI flow
  3. # This should ONLY be invoked after synthesis, and before opt_design.   If opt_design is called first, marked nets may be missing and not found
  4. # Warning: Currently will skip a net if it has no obvious clock domain on the driver.  Nets connected to input buffers will be dropped unless "mark_debug_clock" is attached to the net.
  5. # Nets attached to VIO cores have the "mark_debug" attribute, and will be filtered out unless the "mark_debug_valid" attribute is attached.
  6. # Supports the following additional attributes beyond "mark_debug"
  7. # attribute mark_debug_valid of X : signal is "true";   -- Marks a net for ILA capture, even if net is also attached to a VIO core
  8. # attribute mark_debug_clock of X : signal is "inst1_bufg/clock";  -- Specifies clock net to use for capturing this net.  May create a new ILA core for that clock domain
  9. # attribute mark_debug_depth of X : signal is "4096";              -- overrides default depth for this ILA core. valid values: 1024, 2048, ... 132072.   Last attribute that is scanned will win.
  10. # attribute mark_debug_adv_trigger of X : signal is "true";        -- specifies that advanced trigger capability will be added to ILA core
  11. # Engineer:  J. McCluskey
  12. proc batch_insert_ila { depth } {
  13.    
  14.     set dbgs [get_nets -hierarchical -filter {MARK_DEBUG && NAME !~ "*pcie?_ip_i*"}]
  15.     if {[llength $dbgs] == 0} {
  16.         puts "No nets have the MARK_DEBUG attribute.  No ILA cores created"
  17.         return
  18.     } else {
  19.         puts "ILA_INSERTION: Found [llength $dbgs] nets with MARK_DEBUG"
  20.      
  21.         #process list of nets to find and reject nets that are attached to VIO cores.  This has a side effect that VIO nets can't be monitored with an ILA
  22.         # This can be overridden by using the attribute "mark_debug_valid" = "true" on a net like this.
  23.         set net_list {}
  24.         foreach net $dbgs {
  25.             if { [get_property -quiet MARK_DEBUG_VALID $net] != "true" } {
  26.                 set pin_list [get_pins -of_objects [get_nets -segments $net]]
  27.                 set not_vio_net 1
  28.                 foreach pin $pin_list {
  29.                     if { [get_property IS_DEBUG_CORE [get_cells -of_object $pin]] == 1 } {
  30.                         # It seems this net is attached to a debug core (i.e. VIO core) already, so we should skip adding it to the netlist
  31.                         set not_vio_net 0
  32.                         break
  33.                         }
  34.                     }
  35.                 if { $not_vio_net == 1 } { lappend net_list $net; }
  36.             } else {
  37.                 lappend net_list $net
  38.             }
  39.         }
  40.     }
  41.     # check again to see if we have any nets left now
  42.     if {[llength $net_list] == 0} {
  43.         puts "All nets with MARK_DEBUG are already connected to VIO cores.  No ILA cores created"
  44.         return
  45.     } else {
  46.         puts "ILA_INSERTION: [llength $net_list] nets remain after initial filtering"
  47.     }    
  48.    
  49.     # Now that the netlist has been filtered,  determine bus names and clock domains
  50.     foreach d $net_list {
  51.         # name is root name of a bus, index is the bit index in the
  52.         # bus
  53.         set name [regsub {\[[[:digit:]]+\]$} $d {}]
  54.         set index [regsub {^.*\[([[:digit:]]+)\]$} $d {\1}]
  55.         if {[string is integer -strict $index]} {
  56.             if {![info exists max($name)]} {
  57.                 set max($name) $index
  58.                 set min($name) $index
  59.             } elseif {$index > $max($name)} {
  60.                 set max($name) $index
  61.             } elseif {$index < $min($name)} {
  62.                 set min($name) $index
  63.             }
  64.         } else {
  65.             set max($name) -1
  66.         }
  67.         # Now we search for the local clock net associated with the target net.  There may be ambiguities or no answer in some cases
  68.         if {![info exists clocks($name)]} {
  69.             # does MARK_DEBUG_CLOCK decorate this net?   If not, then search backwards to the driver cell
  70.             set clk_name [get_property -quiet MARK_DEBUG_CLOCK $d]
  71.             if {  [llength $clk_name] == 0 } {
  72.                 # trace to the clock net, tracing backwards via the driver pin.
  73.                 set driver_pin [get_pins -filter {DIRECTION == "OUT" && IS_LEAF == TRUE } -of_objects [ get_nets -segments $d ]]
  74.                 set driver_cell [get_cells -of_objects $driver_pin]
  75.                 if { [get_property IS_SEQUENTIAL $driver_cell] == 1 } {
  76.                     set timing_arc [get_timing_arcs -to $driver_pin]
  77.                     set cell_clock_pin [get_pins -filter {IS_CLOCK} [get_property FROM_PIN $timing_arc]]
  78.                     if { [llength $cell_clock_pin] > 1 } {
  79.                         puts "Error: in batch_insert_ila. Found more than 1 clock pin in driver cell $driver_cell with timing arc $timing_arc for net $d"
  80.                         continue
  81.                         }
  82.                 } else {
  83.                     # our driver cell is a LUT or LUTMEM in combinatorial mode, we need to trace further.
  84.                     set paths [get_timing_paths -quiet -through $driver_pin ]
  85.                     if { [llength $paths] > 0 } {
  86.                         # note that here we arbitrarily select the start point of the FIRST timing path... there might be multiple clocks with timing paths for this net.
  87.                         # use MARK_DEBUG_CLOCK to specify another clock in this case.
  88.                         set cell_clock_pin [get_pins [get_property STARTPOINT_PIN [lindex $paths 0]]]  
  89.                     } else {
  90.                         # Can't find any timing path, so skip the net, and warn the user.                    
  91.                         puts "Critical Warning: from batch_insert_ila.tcl    Can't trace any clock domain on driver of net $d"
  92.                         puts "Please attach the attribute MARK_DEBUG_CLOCK with a string containing the net name of the desired sampling clock, .i.e."
  93.                         puts "attribute mark_debug_clock of $d : signal is \"inst_bufg/clk\";"
  94.                         continue
  95.                     }
  96.                 }  
  97.                 # clk_net will usually be a list of net segments, which needs filtering to determine the net connected to the driver pin
  98.                 set clk_net [get_nets -segments -of_objects $cell_clock_pin]
  99.             } else {
  100.                 set clk_net [get_nets -segments $clk_name]
  101.                 if { [llength $clk_net] == 0 } { puts "MARK_DEBUG_CLOCK attribute on net $d does not match any known net.  Please fix."; continue; }
  102.             }    
  103.             # trace forward to net actually connected to clock buffer output, not any of the lower level segment names
  104.             set clocks($name) [get_nets -of_objects [get_pins -filter {DIRECTION == "OUT" && IS_LEAF == TRUE } -of_objects $clk_net]]
  105.             if {![info exists clock_list($clocks($name))]} {
  106.               # found a new clock
  107.               puts "New clock found is $clocks($name)"
  108.               set clock_list($clocks($name)) [list $name]
  109.               set ila_depth($clocks($name)) $depth
  110.               set ila_adv_trigger($clocks($name)) false
  111.             } else {
  112.               lappend clock_list($clocks($name)) $name
  113.             }
  114.             # Does this net have a "MARK_DEBUG_DEPTH" attribute attached?
  115.             set clk_depth [get_property -quiet MARK_DEBUG_DEPTH $d]
  116.             if { [llength $clk_depth] != 0 } {
  117.                 set ila_depth($clocks($name)) $clk_depth
  118.             }
  119.             # Does this net have a "MARK_DEBUG_ADV_TRIGGER" attribute attached?
  120.             set trigger [get_property -quiet MARK_DEBUG_ADV_TRIGGER $d]
  121.             if { $trigger == "true" } {
  122.                 set ila_adv_trigger($clocks($name)) true
  123.             }
  124.         }
  125.     }
  126.     set ila_count 0
  127.     set trig_out ""
  128.     set trig_out_ack ""
  129.     if { [llength [array names clock_list]] > 1 } {
  130.         set enable_trigger true
  131.     } else {
  132.         set enable_trigger false
  133.     }
  134.     foreach c [array names clock_list] {
  135.         # Now build and connect an ILA core for each clock domain
  136.         [incr ila_count ]
  137.         set ila_inst "ila_$ila_count"
  138.         ##################################################################
  139.         # first verify if depth is a member of the set, 1024, 2048, 4096, 8192, ... 131072
  140.         if { $ila_depth($c) < 1024 || [expr $ila_depth($c) & ($ila_depth($c) - 1)] || $ila_depth($c) > 131072 } {
  141.             # Depth is not right...  lets fix it, and continue
  142.             if { $ila_depth($c) < 1024 } {
  143.                 set new_depth 1024
  144.             } elseif { $ila_depth($c) > 131072 } {
  145.                 set new_depth 131072
  146.             } else {
  147.                 # round value to next highest power of 2, (in log space)
  148.                 set new_depth [expr 1 << int( log($ila_depth($c))/log(2) + .9999 )]
  149.             }
  150.             puts "Can't create ILA core $ila_inst with depth of $ila_depth($c)!  Changed capture depth to $new_depth"
  151.             set ila_depth($c) $new_depth
  152.         }    
  153.         # create ILA and connect its clock
  154.         puts "Creating ILA $ila_inst with capture depth $ila_depth($c) and advanced trigger = $ila_adv_trigger($c)"
  155.         if { [expr [string range [version -short] 0 3] < 2014] } {
  156.             create_debug_core  $ila_inst        labtools_ila_v3
  157.         } else {
  158.             create_debug_core  $ila_inst        ila
  159.         }
  160.         if { $ila_adv_trigger($c) } { set mu_cnt 4; } else { set mu_cnt 2; }
  161.         set_property    C_DATA_DEPTH   $ila_depth($c) [get_debug_cores $ila_inst]
  162.         set_property    C_TRIGIN_EN    $enable_trigger [get_debug_cores $ila_inst]
  163.         set_property    C_TRIGOUT_EN   $enable_trigger [get_debug_cores $ila_inst]
  164.         set_property    C_ADV_TRIGGER  $ila_adv_trigger($c) [get_debug_cores $ila_inst]
  165.         set_property    C_INPUT_PIPE_STAGES 1 [get_debug_cores $ila_inst]
  166.         set_property    C_EN_STRG_QUAL true [get_debug_cores $ila_inst]
  167.         set_property    ALL_PROBE_SAME_MU true [get_debug_cores $ila_inst]
  168.         set_property    ALL_PROBE_SAME_MU_CNT $mu_cnt [get_debug_cores $ila_inst]    
  169.         set_property    port_width 1     [get_debug_ports $ila_inst/clk]
  170.         connect_debug_port $ila_inst/clk    $c
  171.         # hookup trigger ports in a circle if more than one ILA is created
  172.         if { $enable_trigger == true } {
  173.             create_debug_port $ila_inst trig_in
  174.             create_debug_port $ila_inst trig_in_ack
  175.             create_debug_port $ila_inst trig_out
  176.             create_debug_port $ila_inst trig_out_ack
  177.             if { $trig_out != "" } {
  178.                 connect_debug_port $ila_inst/trig_in [get_nets $trig_out]
  179.             }
  180.             if { $trig_out_ack != "" } {
  181.                 connect_debug_port $ila_inst/trig_in_ack [get_nets $trig_out_ack]
  182.             }  
  183.             set trig_out ${ila_inst}_trig_out_$ila_count
  184.             create_net $trig_out
  185.             connect_debug_port  $ila_inst/trig_out [get_nets $trig_out]
  186.             set trig_out_ack ${ila_inst}_trig_out_ack_$ila_count
  187.             create_net $trig_out_ack
  188.             connect_debug_port  $ila_inst/trig_out_ack [get_nets $trig_out_ack]
  189.         }  
  190.         ##################################################################
  191.         # add probes
  192.         set nprobes 0
  193.         foreach n [lsort $clock_list($c)] {
  194.             set nets {}
  195.             if {$max($n) < 0} {
  196.                 lappend nets [get_nets $n]
  197.             } else {
  198.                 # n is a bus name
  199.                 for {set i $min($n)} {$i <= $max($n)} {incr i} {
  200.                     lappend nets [get_nets $n[$i]]
  201.                 }
  202.             }
  203.             set prb probe$nprobes
  204.             if {$nprobes > 0} {
  205.                 create_debug_port $ila_inst probe
  206.             }
  207.             set_property port_width [llength $nets] [get_debug_ports $ila_inst/$prb]
  208.             connect_debug_port $ila_inst/$prb $nets
  209.             incr nprobes
  210.         }
  211.     }
  212.     # at this point, we need to complete the circular connection of trigger outputs and acks
  213.     if { $enable_trigger == true } {
  214.         connect_debug_port ila_1/trig_in [get_nets $trig_out]
  215.         connect_debug_port ila_1/trig_in_ack [get_nets $trig_out_ack]
  216.     }
  217.     set project_found [get_projects -quiet]
  218.     #if { $project_found != "New Project" } {
  219.     #    puts "Saving constraints now in project [current_project -quiet]"
  220.     #    save_constraints_as debug_constraints.xdc
  221.     #}    
  222.     ##################################################################
  223.     implement_debug_core
  224.     ##################################################################
  225.     # write out probe info file
  226.     write_debug_probes -force debug_nets.ltx
  227. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement