/* Program Section: mem_time_analysis.c Revision: 11-Feb-2025 */ /** Declare the Arrays that will hold the Delay Analysis Data **/ double trace_delay[MAX_ARRAY] ; double trace_error_psec[MAX_ARRAY] ; double trace_error_mm[MAX_ARRAY] ; /** Declare some Double Floating Point Variables **/ double ca_bus_avg_delay = 0.0 ; double d0d7_bus_avg_delay = 0.0 ; double d8d15_bus_avg_delay = 0.0 ; double d16d23_bus_avg_delay = 0.0 ; double d24d31_bus_avg_delay = 0.0 ; double bus_delay_total = 0.0 ; double ca_bus_clk_delay = 0.0 ; double d0d7_bus_clk_delay = 0.0 ; double d8d15_bus_clk_delay = 0.0 ; double d16d23_bus_clk_delay = 0.0 ; double d24d31_bus_clk_delay = 0.0 ; /** **/ /** Calculate the Delay in psec of the 71 routes. **/ /** **/ parse_count = 0 ; while( parse_count < INPUT_FILE_LINE_COUNT ) { trace_delay[parse_count] = calculate_delay( \ package_delay[parse_count], \ trace_xy_length[parse_count], \ fraction_on_surface[parse_count], \ via_escape_length[parse_count], \ via_return_length[parse_count], \ via_third_length[parse_count] ) ; ++parse_count ; } /**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++**/ /** **/ /** This First Delay Error Calculation and is based **/ /** on comparing the delay of a given signal to the **/ /** Average Delay of that signal's in that Bus Group **/ /** where the Average Bus Group Delay is based on **/ /** just the Data Type signal in that Bus Group **/ /** and specifically not on the Clock Type signals **/ /** for that Group. **/ /** **/ /**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++**/ /** **/ /** Calculate the Average Delay of the Data Type **/ /** signals in the CA Bus. **/ /** -------- **/ bus_delay_total = 0.0 ; parse_count = 2 ; while( parse_count < 27 ) { bus_delay_total = bus_delay_total + trace_delay[parse_count] ; ca_bus_avg_delay = bus_delay_total / 25.0 ; ++parse_count ; } /** **/ /** Calculate the Average Delay of the Data Type **/ /** signals in the D0:D7 Bus. **/ /** ----------- **/ bus_delay_total = 0.0 ; parse_count = 29 ; while( parse_count < 38 ) { bus_delay_total = bus_delay_total + trace_delay[parse_count] ; d0d7_bus_avg_delay = bus_delay_total / 9.0 ; ++parse_count ; } /** **/ /** Calculate the Average Delay of the Data Type **/ /** signals in the D8:D15 Bus. **/ /** ------------ **/ bus_delay_total = 0.0 ; parse_count = 40 ; while( parse_count < 49 ) { bus_delay_total = bus_delay_total + trace_delay[parse_count] ; d8d15_bus_avg_delay = bus_delay_total / 9.0 ; ++parse_count ; } /** **/ /** Calculate the Average Delay of the Data Type **/ /** signals in the D16:D23 Bus. **/ /** ------------- **/ bus_delay_total = 0.0 ; parse_count = 51 ; while( parse_count < 60 ) { bus_delay_total = bus_delay_total + trace_delay[parse_count] ; d16d23_bus_avg_delay = bus_delay_total / 9.0 ; ++parse_count ; } /** **/ /** Calculate the Average Delay of the Data Type **/ /** signals in the D24:D31 Bus. **/ /** ------------- **/ bus_delay_total = 0.0 ; parse_count = 62 ; while( parse_count < 71 ) { bus_delay_total = bus_delay_total + trace_delay[parse_count] ; d24d31_bus_avg_delay = bus_delay_total / 9.0 ; ++parse_count ; } /** **/ /** Now for each of the 71 signals - Calculate the Error **/ /** between it and the Average for Its Group in pasec. **/ /** **/ /** **/ /** CA Bus Signal Delay Errors wrt CA Bus Average in psec. **/ /** **/ parse_count = 0 ; while( parse_count < 27 ) { trace_error_psec[parse_count] = \ trace_delay[parse_count] - ca_bus_avg_delay ; ++parse_count ; } /** **/ /** D0:D7 Bus Signal Delay Errors wrt D0:D7 Bus Average in psec. **/ /** **/ parse_count = 27 ; while( parse_count < 38 ) { trace_error_psec[parse_count] = \ trace_delay[parse_count] - d0d7_bus_avg_delay ; ++parse_count ; } /** **/ /** D8:D15 Bus Signal Delay Errors wrt D8:D15 Bus Average in psec. **/ /** **/ parse_count = 38 ; while( parse_count < 49 ) { trace_error_psec[parse_count] = \ trace_delay[parse_count] - d8d15_bus_avg_delay ; ++parse_count ; } /** **/ /** D16:D23 Bus Signal Delay Errors wrt D16:D23 Bus Average in psec. **/ /** **/ parse_count = 49 ; while( parse_count < 60 ) { trace_error_psec[parse_count] = \ trace_delay[parse_count] - d16d23_bus_avg_delay ; ++parse_count ; } /** **/ /** D24:D31 Bus Signal Delay Errors wrt D24:D31 Bus Average in psec. **/ /** **/ parse_count = 60 ; while( parse_count < 71 ) { trace_error_psec[parse_count] = \ trace_delay[parse_count] - d24d31_bus_avg_delay ; ++parse_count ; } /** **/ /** Now for each of the 71 signals - Calculate the Error **/ /** between it and the Average for Its Group in mm. **/ /** ---- **/ /** **/ /** The translation from psec to mm is made based **/ /** on whether most of the trace length is on a **/ /** Surface Layer or on an Internal Layer. **/ /** **/ parse_count = 0 ; while( parse_count < INPUT_FILE_LINE_COUNT ) { if (fraction_on_surface[parse_count] > 0.50) { trace_error_mm[parse_count] = \ trace_error_psec[parse_count] / PROP_CNST_SURFACE ; } else { trace_error_mm[parse_count] = \ trace_error_psec[parse_count] / PROP_CNST_INTERNAL ; } ++parse_count ; } /** **/ /** This ends the First Delay Analysis section of the program. **/ /** **/ /** **/ /** Start the First Delay Error Report File Generation **/ /** section of the program. **/ /** **/ /** **/ /** Write out the Trace Delay and Delay Error Information: **/ /** to the Report file: **/ /** **/ /** First write out the Average Delay for the data type **/ /** signals in each of the 5 buses. **/ /** **/ /** Then for each line in the Input Data Files write out: **/ /** **/ /** Pin Number of this Trace **/ /** Net Name of this Trace **/ /** Total delay in psec along this trace **/ /** Difference between this trace and its Group average in psec **/ /** Difference between this trace and its Group average in mm **/ /** **/ fprintf( fp_trace_diff_report_file, \ "\n\n Delay Errors wrt Average Bus Group Delay: \n" ); fprintf( fp_trace_diff_report_file, \ "\n Average CA Bus Delay = %7.2f psec \n", \ ca_bus_avg_delay ); fprintf( fp_trace_diff_report_file, \ " Average D0-D7 Bus Delay = %7.2f psec \n", \ d0d7_bus_avg_delay ); fprintf( fp_trace_diff_report_file, \ " Average D8-D15 Bus Delay = %7.2f psec \n", \ d8d15_bus_avg_delay ); fprintf( fp_trace_diff_report_file, \ " Average D16-D23 Bus Delay = %7.2f psec \n", \ d16d23_bus_avg_delay ); fprintf( fp_trace_diff_report_file, \ " Average D24-D31 Bus Delay = %7.2f psec \n", \ d24d31_bus_avg_delay ); fprintf( fp_trace_diff_report_file, \ "\n\n Pin Net Delay Error Error \n" ); fprintf( fp_trace_diff_report_file, \ " Number Name psec psec mm \n\n" ); parse_count = 0 ; while( parse_count < INPUT_FILE_LINE_COUNT ) { fprintf( fp_trace_diff_report_file, \ "%6s %25s %7.2f %7.2f %7.2f\n", \ array_of_pin_names[parse_count], \ array_of_net_names[parse_count], \ trace_delay[parse_count], \ trace_error_psec[parse_count], \ trace_error_mm[parse_count] ); ++parse_count ; } /** **/ /** This finishes the First Delay Error Report based on a **/ /** given signal's delay wrt its Bus Group's Average Delay. **/ /** **/ /**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++**/ /** **/ /** Now the Second Delay Error Calculation based on **/ /** comparing a given signal's delay to the delay of the **/ /** longest Clock Type signal that services that Bus Group. **/ /** **/ /**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++**/ /** **/ /** For each of the 5 Bus Groups - determine which of its **/ /** two Clock Type signals has the longer delay. **/ /** **/ if ( trace_delay[0] > trace_delay[1] ) { ca_bus_clk_delay = trace_delay[0] ; } else { ca_bus_clk_delay = trace_delay[1] ; } if ( trace_delay[27] > trace_delay[28] ) { d0d7_bus_clk_delay = trace_delay[27] ; } else { d0d7_bus_clk_delay = trace_delay[28] ; } if ( trace_delay[38] > trace_delay[39] ) { d8d15_bus_clk_delay = trace_delay[38] ; } else { d8d15_bus_clk_delay = trace_delay[39] ; } if ( trace_delay[49] > trace_delay[50] ) { d16d23_bus_clk_delay = trace_delay[49] ; } else { d16d23_bus_clk_delay = trace_delay[50] ; } if ( trace_delay[60] > trace_delay[61] ) { d24d31_bus_clk_delay = trace_delay[60] ; } else { d24d31_bus_clk_delay = trace_delay[61] ; } /** **/ /** Now calculate the 71 Delay Errors based on comparing **/ /** each signal to the longer of the two Clock Type signals **/ /** in its Bus Group. **/ /** **/ /** CA Bus Signal Delay Errors wrt CA Bus Average in psec. **/ /** **/ parse_count = 0 ; while( parse_count < 27 ) { trace_error_psec[parse_count] = \ trace_delay[parse_count] - ca_bus_clk_delay ; ++parse_count ; } /** **/ /** D0:D7 Bus Signal Delay Errors wrt D0:D7 Bus Average in psec. **/ /** **/ parse_count = 27 ; while( parse_count < 38 ) { trace_error_psec[parse_count] = \ trace_delay[parse_count] - d0d7_bus_clk_delay ; ++parse_count ; } /** **/ /** D8:D15 Bus Signal Delay Errors wrt D8:D15 Bus Average in psec. **/ /** **/ parse_count = 38 ; while( parse_count < 49 ) { trace_error_psec[parse_count] = \ trace_delay[parse_count] - d8d15_bus_clk_delay ; ++parse_count ; } /** **/ /** D16:D23 Bus Signal Delay Errors wrt D16:D23 Bus Average in psec. **/ /** **/ parse_count = 49 ; while( parse_count < 60 ) { trace_error_psec[parse_count] = \ trace_delay[parse_count] - d16d23_bus_clk_delay ; ++parse_count ; } /** **/ /** D24:D31 Bus Signal Delay Errors wrt D24:D31 Bus Average in psec. **/ /** **/ parse_count = 60 ; while( parse_count < 71 ) { trace_error_psec[parse_count] = \ trace_delay[parse_count] - d24d31_bus_clk_delay ; ++parse_count ; } /** **/ /** Now for each of the 71 signals - Calculate the Error **/ /** between it and the longer Clock for Its Group in mm. **/ /** ---- **/ /** **/ /** The translation from psec to mm is made based **/ /** on whether most of the trace length is on a **/ /** Surface Layer or on an Internal Layer. **/ /** **/ parse_count = 0 ; while( parse_count < INPUT_FILE_LINE_COUNT ) { if (fraction_on_surface[parse_count] > 0.50) { trace_error_mm[parse_count] = \ trace_error_psec[parse_count] / PROP_CNST_SURFACE ; } else { trace_error_mm[parse_count] = \ trace_error_psec[parse_count] / PROP_CNST_INTERNAL ; } ++parse_count ; } /** **/ /** This ends the Second Delay Analysis section of the program. **/ /** **/ /** **/ /** Start the Second Delay Error Report File Generation **/ /** section of the program. **/ /** **/ /** **/ /** Write out the Trace Delay and Delay Error Information: **/ /** to the Report file: **/ /** **/ /** First write out the longer of the two Clock Delays **/ /** for each of the 5 Buses Groups. **/ /** **/ /** Then for each line in the Input Data Files write out: **/ /** **/ /** Pin Number of this Trace **/ /** Net Name of this Trace **/ /** Total delay in psec along this trace **/ /** Difference between this trace and its Group average in psec **/ /** Difference between this trace and its Group average in mm **/ /** **/ fprintf( fp_trace_diff_report_file, \ "\n\n Delay Errors wrt Bus Group's Clock Delay: \n" ); fprintf( fp_trace_diff_report_file, \ "\n CA Bus Clock Delay = %7.2f psec \n", \ ca_bus_clk_delay ); fprintf( fp_trace_diff_report_file, \ " D0-D7 Bus Clock Delay = %7.2f psec \n", \ d0d7_bus_clk_delay ); fprintf( fp_trace_diff_report_file, \ " D8-D15 Bus Clock Delay = %7.2f psec \n", \ d8d15_bus_clk_delay ); fprintf( fp_trace_diff_report_file, \ " D16-D23 Bus Clock Delay = %7.2f psec \n", \ d16d23_bus_clk_delay ); fprintf( fp_trace_diff_report_file, \ " D24-D31 Bus Clock Delay = %7.2f psec \n", \ d24d31_bus_clk_delay ); fprintf( fp_trace_diff_report_file, \ "\n\n Pin Net Delay Error Error \n" ); fprintf( fp_trace_diff_report_file, \ " Number Name psec psec mm \n\n" ); parse_count = 0 ; while( parse_count < INPUT_FILE_LINE_COUNT ) { fprintf( fp_trace_diff_report_file, \ "%6s %25s %7.2f %7.2f %7.2f\n", \ array_of_pin_names[parse_count], \ array_of_net_names[parse_count], \ trace_delay[parse_count], \ trace_error_psec[parse_count], \ trace_error_mm[parse_count] ); ++parse_count ; } fclose( fp_trace_diff_report_file ) ; /** **/ /** This finishes the Second Delay Error Report based on a **/ /** given signal's delay wrt its Bus Group's Longer Clock Delay. **/ /** **/ return (1); } /** **/ /** End of the main program - now for the Function Definitions **/ /** **/ /** **/ /** This is the calculate_delay function. It is called **/ /** for each of the 71 lines in the input data files **/ /** **/ /** When calling this function the arguments are: **/ /** **/ /** X,Y 2d Trace Length in mm **/ /** Package Delay in psec **/ /** Fraction of Trace Length that is on a Surface Layer **/ /** Length of the FPGA BGA Escape Via in mm **/ /** Length of the Memory Chip Return Via in mm **/ /** Length of a 3rd Via if one is used in mm **/ /** **/ /** This function has access to the Surface, Internal, **/ /** and Via Propagation Constants that were Defined **/ /** near the top of the read files program section. **/ /** Propagation Constants are in psec/mm **/ /** **/ /** This function returns the overall delay **/ /** in psec of this route. **/ /** **/ double calculate_delay( double package_delay, double xy_length, \ double surface_fraction, double escp_via, \ double return_via, double extra_via ) { double delay_psec = 0.0 ; delay_psec = package_delay + \ ( xy_length * surface_fraction * PROP_CNST_SURFACE ) + \ ( xy_length * ( 1.0 - surface_fraction) * PROP_CNST_INTERNAL ) + \ ( (escp_via + return_via + extra_via) * PROP_CNST_VIA ) ; return (delay_psec) ; }