Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / share / tcl / wrapup_report.tcl
1 ########################################################################
2 # #
3 # Set of procedures to generate a wrapup report of a list of slacks #
4 # #
5 # Slacks are grouped together if the names of start, end, and thru #
6 # nodes are similar. Node names are similar if the only differences #
7 # are indexes suffixed at the end of name segments. #
8 # #
9 ########################################################################
10
11 ########################################################################
12 # #
13 # For a given slack create a string which is a colon separated list of #
14 # the start, thru and end names #
15 # #
16 ########################################################################
17
18 proc get_slack_name {slack} {
19 set event [stb_GetSlackProperty $slack START_EVENT]
20 set signal [ttv_GetTimingEventProperty $event SIGNAL]
21 set start_name [ttv_GetTimingSignalProperty $signal NET_NAME]
22
23 set event [stb_GetSlackProperty $slack END_EVENT]
24 set signal [ttv_GetTimingEventProperty $event SIGNAL]
25 set end_name [ttv_GetTimingSignalProperty $signal NET_NAME]
26
27 set event [stb_GetSlackProperty $slack THRU_EVENT]
28 if {$event != "NULL"} {
29 set signal [ttv_GetTimingEventProperty $event SIGNAL]
30 set thru_name [ttv_GetTimingSignalProperty $signal NET_NAME]
31 } else {
32 set thru_name ""
33 }
34
35 return "$start_name:$thru_name:$end_name"
36 }
37
38 proc get_path_name {path} {
39 set event [ttv_GetTimingPathProperty $path START_EVENT]
40 set signal [ttv_GetTimingEventProperty $event SIGNAL]
41 set start_name [ttv_GetTimingSignalProperty $signal NET_NAME]
42
43 set event [ttv_GetTimingPathProperty $path END_EVENT]
44 set signal [ttv_GetTimingEventProperty $event SIGNAL]
45 set end_name [ttv_GetTimingSignalProperty $signal NET_NAME]
46
47 set event [ttv_GetTimingPathProperty $path ACCESS_LATCH]
48 if {$event != "NULL"} {
49 set signal [ttv_GetTimingEventProperty $event SIGNAL]
50 set thru_name [ttv_GetTimingSignalProperty $signal NET_NAME]
51 } else {
52 set thru_name ""
53 }
54
55 return "$start_name:$thru_name:$end_name"
56 }
57
58 ########################################################################
59 # #
60 # Create bus notation form from an unsorted set of bus indices #
61 # #
62 ########################################################################
63
64 proc get_bus {bus_indices} {
65 set bus_indices [lsort -integer $bus_indices]
66 set bus [lindex $bus_indices 0]
67 set last_index $bus
68 set last_bus $bus
69 foreach index $bus_indices {
70 if {$index == $last_index} continue
71 if {$index != [expr $last_index+1]} {
72 if {$last_index == $last_bus} {
73 set bus "$bus,$index"
74 } else {
75 set bus "$bus-$last_index,$index"
76 }
77 set last_bus $index
78 }
79 set last_index $index
80 }
81 if {$last_index != $last_bus} {
82 set bus "$bus-$last_index"
83 }
84 return "$bus"
85 }
86
87 ########################################################################
88 # #
89 # Function which does most of the work #
90 # #
91 # Input: A list of slacks #
92 # Output: An array of typical slacks #
93 # Each element of this array is a 2-element list where the #
94 # first element is a string made up of colon separated start, #
95 # end, and thru names in bus notation and the second element #
96 # is an example of this slack #
97 # #
98 ########################################################################
99
100 proc get_typical_slacks {slacks typical_slacks get_name_func} {
101 upvar $typical_slacks typical_slack_array
102 set base_name_count 0
103 set slackcount 0
104
105 foreach slack $slacks {
106 set slack_name [$get_name_func $slack]
107 set index_list [regexp -all -inline {[0-9]+[:\/\.]|[0-9]+$} $slack_name]
108 if {[llength index_list] > 0} {
109 regsub -all {[0-9]+([:\/\.])|[0-9]+$} $slack_name {\[%s\]\1} base_name
110 if {$base_name_count == 0} {
111 set base_names(1) $base_name
112 set indices(1) [list $index_list]
113 set example_slacks(1) $slack
114 set group_count(1) 1
115 set base_name_count 1
116 puts "$slackcount : $base_name_count : $slack_name"
117 } else {
118 set match 0
119 foreach i [array names base_names] {
120 if {$base_names($i) == $base_name} {
121 lappend indices($i) $index_list
122 incr group_count($i) 1
123 set match 1
124 break
125 }
126 }
127 if {$match == 0} {
128 incr base_name_count 1
129 set base_names($base_name_count) $base_name
130 set indices($base_name_count) [list $index_list]
131 set example_slacks($base_name_count) $slack
132 set group_count($base_name_count) 1
133 puts "$slackcount : $base_name_count : $slack_name"
134 }
135 }
136 }
137 incr slackcount 1
138 }
139
140 foreach i [array names base_names] {
141 set count [llength [lindex $indices($i) 0]]
142 set bus_list ""
143 for {set j 0} {$j < $count} {incr j 1} {
144 set bus ""
145 foreach index_list $indices($i) {
146 lappend bus [string trimright [lindex $index_list $j] :./]
147 }
148 set bus [get_bus $bus]
149 set bus_list "$bus_list $bus"
150 }
151 set bussed_name [eval format $base_names($i) $bus_list]
152 set typical_slack_array($i) [list $bussed_name $example_slacks($i) $group_count($i)]
153 }
154 }
155
156 ########################################################################
157 # #
158 # Display a given bus grouping where start, end and thru nodes are #
159 # colon separated #
160 # #
161 ########################################################################
162
163 proc display_bussed_slack_name {file slack_name index count total labelc } {
164 regsub -all : $slack_name " " slack_name_list
165 fputs "Bus Grouped $labelc ($index) : $count objects (out of $total)\n\n" $file
166 fputs " From: [lindex $slack_name_list 0]\n" $file
167 if {[llength $slack_name_list] == 3} {
168 fputs " To: [lindex $slack_name_list 2]\n" $file
169 fputs " Thru: [lindex $slack_name_list 1]\n\n" $file
170 } else {
171 fputs " To: [lindex $slack_name_list 1]\n\n" $file
172 }
173 }
174
175 ########################################################################
176 # #
177 # Display the details of a given slack #
178 # #
179 ########################################################################
180
181 proc display_slack_detail {file slack index lagdebug} {
182 set value [format "%.1fps" [expr 1e12*[stb_GetSlackProperty $slack VALUE]]]
183 fputs "Example of Bus Grouped Slack ($index) : Slack of $value\n\n" $file
184 if {$lagdebug == 1} {
185 set path [stb_GetSlackProperty $slack DATA_VALID_PATH]
186 if {[ttv_GetTimingPathProperty $path DATA_LAG] > 0} {
187 stb_FindLagPaths $file $slack -closingpath
188 } else {
189 stb_DisplaySlackReport $file -slacks $slack
190 }
191 } else {
192 stb_DisplaySlackReport $file -slacks $slack
193 }
194 }
195
196 proc display_path_detail {file path index lagdebug} {
197 set value [format "%.1fps" [expr 1e12*[ttv_GetTimingPathProperty $path DELAY]]]
198 fputs "Example of Bus Grouped Path ($index) : Delay of $value\n\n" $file
199 ttv_DisplayPathDetail $file $index $path
200 }
201
202 ########################################################################
203 # #
204 # The top-level function for the wrap-up report #
205 # #
206 ########################################################################
207
208 proc write_wrapup_report_any {file slacks get_name_func display_detail_func labelc lagdebug} {
209 get_typical_slacks $slacks typical_slacks $get_name_func
210
211 set total_slacks [llength $slacks]
212 foreach i [lsort -integer [array names typical_slacks]] {
213 display_bussed_slack_name $file [lindex $typical_slacks($i) 0] $i [lindex $typical_slacks($i) 2] $total_slacks $labelc
214 $display_detail_func $file [lindex $typical_slacks($i) 1] $i $lagdebug
215 }
216 }
217
218 proc write_wrapup_report {file slacks args} {
219 global tcl_interactive
220 set i 0
221 set lagdebug 0
222
223 set lst $args
224 while {[lindex $lst $i]!=""} {
225 set opt [lindex $lst $i]
226 incr i
227 if {$opt=="-lagdebug"} {
228 set lagdebug 1
229 } else {
230 set prei [expr $i-1]
231 puts "Unknown option '[lindex $lst $prei]'"
232 puts "Usage: write_wrapup_report <file> <slacklist> \[-lagdebug]"
233 if {!$tcl_interactive} {
234 exit
235 } else {
236 return [_NULL_]
237 }
238 }
239 }
240 if {[string first "TimingPath" [lindex $slacks 0]]!=-1} {
241 write_wrapup_report_any $file $slacks get_path_name display_path_detail Path $lagdebug
242 } else {
243 write_wrapup_report_any $file $slacks get_slack_name display_slack_detail Slack $lagdebug
244 }
245 }
246
247
248
249 #----------------------------------------------------------------------