list_path 및 report_timing Tcl 명령은 매우 강력하지만 몇 가지 제한이 있습니다. 경로 끝점은 클럭, 핀 또는 레지스터여야 합니다. 또한 이러한 명령은 끝점 사이의 모든 조합 경로를 보고하지 않습니다. 이 고급 스크립트 예는 설계의 임의 경로(조합 끝점 포함)에 대한 보고 타이밍을 지원하며 엔드포인트 간의 모든 조합 경로를 보고합니다. 스크립트는 반복 검색 알고리즘을 사용하여 경로를 찾습니다. 알고리즘은 핀에서 멈추고 등록하여 과도한 실행 시간을 방지합니다.
소스 및 대상에 대한 노드 이름, 와일드카드 또는 시간 그룹 이름을 지정할 수 있습니다. 시간 그룹 제외는 이 스크립트에서 지원하지 않습니다. 끝점에 대한 제외가 포함된 시간 그룹을 지정하고 제외를 무시하면 경고가 표시됩니다.
스크립트 출력을 쉼표 분리값(.csv)파일로 직접 보낼 수 있습니다. 기본 파일 이름은 p2p_timing.csv. 또한 프로젝트의 타이밍 보고서에 있는 패널로 스크립트 출력을 지시할 수 있습니다. 기본 패널 이름은 Point-to-point Timing입니다.
quartus_tan -t p2p_timing.tcl -project <프로젝트 이름> -에서 <노드 이름|wildcard|timegroup 이름> -에서 <노드 이름|wildcard|timegroup 이름> [-write_file] [-파일 <output 파일 이름>] [-write_panel] [-패널 <레포트 패널 이름>]
출력을 기본 파일 이름과 다른 파일로 연결하려면 -write_file 및 -file <output 파일 이름> 옵션을 모두 지정해야 합니다. 출력을 기본 보고서 패널 이름과 다른 보고서 패널로 연결하려면 -write_panel 및 -panel <리포트 패널 이름> 옵션을 모두 지정해야 합니다.
다음 Tcl 명령을 파일에 복사하여 p2p_timing.tcl.
패키지에는 cmdline이 필요합니다. load_package advanced_timing load_package 보고서 글로벌 쿼투스 변수 ::argv0 $::quartus(args) 설정 옵션 { \ { "from.arg" "" "소스 노드 이름" } \ { "to.arg" "" "대상 노드 이름" } \ { "project.arg" "" "프로젝트 이름" } \ { "file.arg" "p2p_timing.csv" "출력 csv 파일 이름" } \ { "write_file" ""파일에 출력 쓰기" } \ { "panel.arg" "포인트 투 포인트 타이밍" "보고서 패널 이름" } \ { "write_panel" "보고서 패널에 출력 쓰기" } \ } 배열 세트 옵트 [::cmdline::getoptions::argv0 $options "불량 옵션"] ############################################################## # # 노드 이름과 해당 노드 ID 목록을 반환합니다. 패턴 인수와 일치하는 디자인 이름에 대한 # # 디자인의 이름과 일치하지 않는 모든 패턴에는 # 빈 목록 반환 # 예: "재설정"을 전달하고 { 재설정 3 }을 다시 받으십시오. # ############################################################## proc get_node_ids { 패턴 } { 배열 세트 name_to_node [목록] {[문자열이 "같음" $pattern] } { 반품 [목록] } # 패턴이 실제로 시간 그룹의 이름입니까? # 이 경우 스크립트가 재귀적으로 구성원을 가져옵니다. # 시간 그룹. 설정 멤버 [get_all_global_assignments -name TIMEGROUP_MEMBER -section_id $pattern] # 컬렉션의 구성원이 있는 경우, # 패턴은 시간 그룹입니다. {0 < [get_collection_size $members]} { # 스크립트가 있기 때문에 제외 사항이 있는 경우 경고 # 제외 건너뛰기 {0 < [get_collection_size[get_all_global_assignments -name TIMEGROUP_EXCLUSION -section_id $pattern]] } { post_message -type 경고 "시간 그룹 $pattern 제외 건너뛰기" } # 시간 그룹의 각 항목을 확인합니다. foreach_in_collection 할당 $members { # 컬렉션의 각 항목은 다음과 같은 목록입니다. #{$pattern} {TIMEGROUP_MEMBER} {노드/실제 패턴} 배열 세트 sub_collection_names [get_node_ids [lindex $assignment 2]] foreach node_name [배열 이름 sub_collection_names] { name_to_node($node_name) $sub_collection_name($node_name) 설정 } } } 기타 { # 시간 그룹이 아닙니다. # 설계의 모든 타이밍 노드를 반복합니다. # 이름이 지정된 패턴과 일치하는지 확인 foreach_in_collection node_id [get_timing_nodes -type all] { node_name 설정 [get_timing_node_info -info name $node_id] {[문자열 일치[escape_brackets $pattern] $node_name] } { name_to_node($node_name) $node_id 설정 } } } 반품 [어레이 name_to_node] } ############################################################## # # 이 절차는 소스 간의 조합 경로를 찾습니다. # 노드 및 대상 노드 목록. 목록 반환 노드 간 경로 수입니다. 각 경로는 트리플릿으로 구성됩니다. 노드 ID 수 및 상호 연결 지연 및 셀 지연 # 이전 노드. # 레지스터에서 넷리스트 통과를 중지하는 절차 # 또는 핀, 그래서 레지스터를 통해 이동 경로를 찾을 수 없습니다. # ############################################################## proc find_combinational_paths_between {큐 dest_nodes} { num_iterations 0으로 설정 경로 설정 [목록] {0 < [llength $queue]} { # 1,000회 루프 진행 상황 보고 # 반복 인크 num_iterations {1000 == $num_반복} { num_iterations 0으로 설정 post_message "[llength $queue] 경로를 확인하십시오." } # 대기열에서 첫 번째 경로를 팝업합니다. # 프로시저가 처음 호출되면 큐 #은 하나의 숫자, 소스 노드입니다. 설정 경로 [lindex $queue 0] 큐 설정 [lrange $queue 1엔드] # 경로의 마지막 노드를 구한 다음 포어치 루프에서 해당 노드에서 팬아웃 받기 last_triplet_in_path 설정 [lindex $path 끝] last_node_in_path 설정 [lindex $last_triplet_in_path 0] # 현재 경로의 노드 ID만 추출합니다. # 이것은 루프가 통과되지 않도록 하기 위해 나중에 사용됩니다. 세트 nodes_in_path [collapse_triplets_to_node_list $path] # 이 경로의 마지막 노드의 모든 팬아웃을 확보하고 대기열에서 밀어붙일 수 있는 새로운 경로 수입니다. foreach n [get_timing_node_fanout $last_node_in_path] { foreach { node_id ic_delay cell_delay } $n { 휴식 } {-1!= [lsearch $dest_노드 $node_id] } { 경로에 있는 이 노드가 목록에 있는 경우 대상 노드 수, 경로가 있습니다. # 노드 간 경로 목록에 추가 new_path $path 랩펜 설정 new_path $n lappend 경로 $new_path } {-1 == [lsearch $nodes_in_path $node_id] } { 경로에 있는 이 노드가 경로에 없는 경우 # 이미, 이것은 루프가 아닙니다. 에 밀어 조합 노드 또는 클럭 노드인 경우 # 큐. 이 노드가 있는 경우 경로가 푸시되지 않음 # 등록 또는 핀. 이처럼 대기열에서 새로운 경로를 밀어붙이는 경우 경로에 있는 이 노드가 일치할 수 있더라도 # 엔드 노드 수, 가능한 가장 긴 노드 보장 # 경로가 있습니다. node_type 설정 [get_timing_node_info -info type $node_id] 스위치 -exact -- $node_type { 빗 - clk { next_path $path 설정 랩펜드 next_path $n lappend 큐 $next_path } 기본값 { } } } } } 반품 $paths } ############################################################## # # 지연 번호 2개를 추가하고 결과를 반환합니다. # 지연 번호는 단위가 있는 "값 단위" 형태입니다. #는 나노초(ns) 또는 picoseconds(ps)일 수 있으며, 값은 단위가 picoseconds인 경우 x{1,3} 또는 x+.y{1,3} #단위는 나노초입니다. 이 절차는 지연을 정상화합니다. #nanoseconds 및 값을 추가합니다. # 예: add_delays "1.234 ns" "56 ps" # ############################################################## proc add_delays { b } { { 경우 {[] regexp {^([\d\.] +)\s+([np]s)$} $a 일치 a_value a_unit] } { post_message -type 오류 "시간의 일부를 확인할 수 없습니다: $a" } { 경우 {[] regexp {^([\d\.] +)\s+([np]s)$} $b 일치 b_value b_unit] } { post_message -type 오류 "시간의 일부를 확인할 수 없습니다: $b" } # 필요한 경우 모든 것을 나노초로 변환 {[문자열 동일 -nocase ps $a_unit] } { a_value_ps 설정 [포맷 "%.3f" $a_value] a_value 설정 [포맷 "%.3f"[expr { $a_value_ps / 1000 }]] } {[문자열 동일 -nocase ps $b_unit] } { b_value_ps 설정 [포맷 "%.3f" $b_value] b_value 설정 [포맷 "%.3f"[expr { $b_value_ps / 1000 }]] } # 이제 단위는 같고 나노초입니다. # 숫자를 함께 추가하기만하면됩니다. sum_value 설정 [포맷 "%.3f"[expr { $a_value + $b_value }]] 반환 "$sum_value ns" } ############################################################## # # 경로에 노드 이름을 포맷하고 인쇄합니다. 노드 간 지연 수입니다. # ############################################################## proc print_path_delays {path {반복 첫 번째}} { 세트 source_triplet [lindex $path 0] 세트 source_node [lindex $source_triplet 0] source_node_name 설정 [get_timing_node_info -info name $source_node] source_node_loc 설정 [get_timing_node_info -info 위치 $source_node] # 지연을 먼저 인쇄합니다. {[문자열이 "첫 번째" $iteration]} { accumulate_data [목록 "IC(0.000 ns)" "CELL(0.000 ns)") } 기타 { 세트 ic_delay [lindex $source_triplet 1] 세트 cell_delay [lindex $source_triplet 2] accumulate_data [목록 "IC($ic_delay)" "CELL($cell_delay)") } accumulate_data [목록 $source_node_loc $source_node_name] print_accumulated_data 경로의 나머지 부분에 대해 #Recurse {1 < [llength $path] } { print_path_delays [lrange $path 1엔드] 기타 } } ############################################################## # # 지정된 경로의 IC 및 셀 지연을 합산하고 # 총 상호 연결 지연 및 총 셀이 있는 목록을 반환합니다. # 지연. # ############################################################## proc end_to_end_delay {path } { "0.000 ns"ic_total 설정 cell_total "0.000 ns" 설정 #이 노드 1을 통과하여 경로에서 종료됩니다. 경로의 첫 번째 노드는 소스와 경로의 각 노드입니다. # 경로에는 노드 앞에 있는 노드의 지연이 포함됩니다. Tthe # 소스 앞에 노드가 없으므로 지연이 없습니다. foreach n [lrange $path 1엔드] { foreach { node_id ic_delay cell_delay } $n { 휴식 } ic_total 설정 [add_delays $ic_total $ic_delay] cell_total 설정 [add_delays $cell_total $cell_delay] } 반품 [목록 $ic_total $cell_total] } ############################################################## # # 지정된 소스와 대상이 해당 소스에 있는지 확인합니다. # 설계, 그들 사이의 조합 경로를 찾습니다. #은 경로를 인쇄합니다. # ############################################################## proc find_paths_and_display { 소스 dest } { 배열 세트 소스 [get_node_ids $source] 배열 세트 디스트 [get_node_ids $dest] 세트 nodes_exist 1 # 명명된 노드가 있는지 확인 {0 == [llength [어레이 가져오기 소스]] } { nodes_exist 0 설정 post_message -type 오류 "설계에서 $source 일치하는 노드가 없습니다." } {0 == [llength[array get dests]] } { nodes_exist 0으로 설정 post_message -type 오류 "설계에서 $dest 일치하는 노드가 없습니다." } # 만약 그렇게 한다면, 경로를 찾아보십시오. {$nodes_exist } { # 대상 노드 ID 목록 가져오기 dest_node_ids 설정 [목록] foreach d [배열 이름 dests] { lappend dest_node_ids $dests($d) } # 노드에서 온 모든 것을 훑어보십시오 foreach s [배열 이름 소스] { 경로 설정 [find_combinational_paths_between $sources($s) $dest_node_ids] {0 == [llength $paths] } { post_message "$s $dest 조합 경로가 없습니다" } 기타 { 포리치 경로 $paths { # 경로 인쇄 print_path_delays $path # 상호 연결 및 셀 지연을 합산하고 # 경로 아래에 인쇄하십시오. foreach {total_ic_delay total_cell_delay } [end_to_end_delay $path] { 휴식 } accumulate_data [목록 $total_ic_delay $total_cell_delay] accumulate_data [목록[add_delays $total_ic_delay $total_cell_delay]] # print_accumulated_data 두 번의 통화가 있습니다. # 여기, 상호 연결의 합계를 인쇄할 수 있습니다. # 및 셀 지연, 공백을 생성할 수 있는 지연 출력에서 # 라인. print_accumulated_data print_accumulated_data } } } } } ############################################################## # # 경로는 정보의 삼중으로 구성됩니다 - 노드 ID, # 상호 연결 지연 및 셀 지연. 이 절차는 추출합니다. 각 트리플릿의 노드 ID를 순서대로 표시하고 목록을 반환합니다. 노드 ID 수 # ############################################################## proc collapse_triplets_to_node_list { l } { to_return 설정 [목록] 포리치 트리플릿 $l { lappend to_return [lindex $triplet 0] } 반품 $to_return } ############################################################## # # 준비 중인 글로벌 변수에 대한 정보를 Concatenates # 인쇄되는 경우. # ############################################################## proc accumulate_data { 데이터 } { 글로벌 accum 세트 accum [concat $accum $data] } ############################################################## # # 누적된 데이터를 인쇄합니다. # 표준 출력 및 선택적으로 파일로 인쇄됩니다. 파일 핸들이 있는 경우, 선택적으로 CSV 형식 보고서 패널이 존재하는 경우 #Report Panel(-1의 값이 아님) # ############################################################## proc print_accumulated_data {} { 글로벌 accum fh panel_id [$accum"에 참여하십시오. # 파일에 기록하시겠습니까? { [정보가 fh 존재] } { $fh ["$accum 참여"] } # 보고서 패널에 추가하시겠습니까? {-1!= $panel_id } { # 보고서 패널 행에 4개 항목이 없는 경우 # 그것에, 4에 패드. { 4 > [llength $accum] } { lappend accum [목록] } add_row_to_table -id $panel_id $accum } # 전역 변수의 정보를 지웁시기. accum 설정 [목록] } ############################################################## ############################################################## # # 절차 종료, 스크립트 시작 # ############################################################## ############################################################## # 인쇄용 데이터를 보관할 수 있는 글로벌 변수 수 및 패널 옵션 보고서 패널의 ID 수 accum 설정 [목록] panel_id -1 설정 {[문자열이 "" $opts(project)] } { 스크립트가 호출되지 않은 경우 # 인쇄 사용 옵션 # 인수 [::cmdline:::사용량 $options] } elseif {[문자열 동일 "" $opts(project)] } { post_message -type 오류 "-project 옵션으로 프로젝트 지정" } elseif {! [project_exists $opts(프로젝트)] } { post_message -type 오류 "프로젝트 $opts(project)가 이 디렉토리에 존재하지 않습니다." } elseif {[문자열 동일 "" $opts(에서) } { post_message -type 오류 "-from 옵션으로 이름 또는 와일드카드 패턴을 지정합니다." } elseif {[문자열이 "같음" $opts(to)] } { post_message -type 오류 "-to 옵션으로 이름 또는 와일드카드 패턴을 지정합니다." } 기타 { cur_revision 설정 [get_current_revision $opts(프로젝트)] project_open $opts(프로젝트) -개정 $cur_개정 # 타이밍 넷리스트를 만들어 보십시오. 이 명령은 실패합니다. 예를 들어 quartus_fit 아직 실행되지 않은 경우. {[catch { create_timing_netlist } msg] } { post_message -type 오류 $msg } 기타 { # 필요한 경우 파일에 출력을 작성할 준비를 합니다. {1 == $opts(write_file) } { {[catch {open $opts(파일) w} fh] } { post_message -type 오류 "$opts 열 수 없습니다(write_file): $fh" unset fh } 기타 { post_message "$opts(파일)에 출력 쓰기" # 출력 파일에 몇 가지 소개 정보 추가 $fh "$opts(에서 $opts)로의 경로 보고" $fh "[클럭 형식[클럭 초]에서 생성됨]" "IC 지연, 셀 지연, 노드 위치, 노드 이름"을 $fh $fh 넣습니다. } } # 필요한 경우 보고서 패널에 출력을 작성할 준비를 합니다. {1 == $opts(write_panel) } { # 보고서 로드, 패널이 이미 있는 경우 삭제, # 새 패널을 만들고 제목 행을 추가합니다. load_report 설정 panel_id [get_report_panel_id "타이밍 분석기|| $opts(패널)"] {-1!= $panel_id } { delete_report_panel -id $panel_id } 설정 panel_id [create_report_panel -table "타이밍 분석기"|| $opts(패널)"] add_row_to_table -id $panel_id [목록 "IC 지연" "셀 지연" "노드 위치" "노드 이름"] } find_paths_and_display $opts(부터) $opts(~) 필요한 경우 출력 파일을 닫습니다. { [정보가 fh 존재] } { $fh 닫으면 } # 필요한 경우 보고서 패널 저장 {-1!= $panel_id } { save_report_database unload_report } } project_close }