- •Contents
- •Introduction
- •About These Application Notes
- •What Is a Cell?
- •Cell Interconnect Delays
- •What Is Delay Back Annotation?
- •What Is Delay Calculation?
- •Prerequisites and Related Reading
- •Creating a Back Annotator
- •The Programming Language Interface (PLI) Mechanism
- •PLI Access Routines
- •Access Routine Families
- •Required UTILITY Routines
- •Access to Timing Information
- •Effect of Source Protection
- •Where to Look for More Information
- •Back Annotating Delays
- •Examples Used in This Chapter
- •Retrieving a Handle to the Object Associated with the Delay
- •Retrieving a Handle to a Net
- •Retrieving a Handle to a Module Path Delay
- •Retrieving a Handle to a Timing Check
- •Annotating the Delay
- •Determining How and Where to Place Delays
- •Annotating to Cells with Path Delays
- •Annotating to Cells with Lumped or Distributed Delays
- •Libraries with Mixed Cell Timing Descriptions
- •Annotating to Timing Checks
- •Calculating Delays
- •Examples Used in This Chapter
- •Scanning Cell Instances Within the Design
- •Determining the Scope of the Delay Calculation
- •Scan Methodology
- •Scanning Objects Within the Cell Instance
- •Relationship to Modeling Methodology
- •Scanning Path Delays
- •Scanning Cell Output Ports
- •Libraries with Mixed Cell Timing Descriptions
- •Types of Data Needed
- •Coding Data into Cell Descriptions (Attributes)
- •Retrieving Cell I/O Load Factors
- •Load Due to Interconnect Wire
- •Calculating and Annotating the Delays
- •Calculating the Delays
- •Annotating the Delays
- •Example Listings
- •Delay Back Annotators
- •Cell Output Nets to Lumped or Distributed Delay Cells
- •Interconnect Nets to Lumped or Distributed Delay Cells
- •Cell Output Nets to Path Delay Cells
- •Interconnect Nets to Path Delay Cells
- •Delay Calculators
- •Creating and Extracting Data From a Hash Table
- •Random Cell Scan and Cell Output Nets
- •Random Cell Scan and Cell Interconnect Nets
- •Delay Calculation Driven by Cell Output Nets
- •Delay Calculation Driven by a Cell Interconnect Nets
- •Index
Back Annotation and Delay Calculation
Example Listings
static int dl_get_numlines(filename) char *filename;
{
int line = 0; double val; FILE *net_file; char name[256];
if ((net_file = fopen(filename,"r")) == 0)
{
io_printf("Warning: Back-annotate file \"%s\" not found.\n", filename);
return(0);
}
while (fscanf(net_file,"%s%lf\n",name,&val) != EOF) line++;
fclose(net_file); return(line);
}
Random Cell Scan and Cell Output Nets
Figure 5-7 on page 110 shows a set of routines that comprise two delay calculators: one that calculates delays for designs that use cells described with lumped or distributed (primitive output) delay timing, and one for designs that use cells described with path delay timing. Both delay calculators use acc_next_cell to randomly scan the cell instances in the design. Both also take an optional capacitance back annotation file that contains cell output net names and their associated capacitance values. Note that the two delay calculators share a large set of common source code.
The system tasks associated with these delay calculators accept zero, one, or two arguments, where the arguments specify the following information:
1.the top of the hierarchical tree for which delays are to be calculated (a module instance name)
2.the capacitance back annotation file (a file name enclosed in double quotes)
If you do not provide the first system task argument, the delay calculator will calculate delays for all cells below the scope that contains the system task call. If you do not provide the second system task argument, or if the second argument is ‘estimated,’ the delay calculator will estimate interconnect wire capacitance. For more detailed information about the operation and invocation of these delay calculators, refer to the header comments in the actual delay calculator source file provided with your Veritool release.
These delay calculators use the routines described in “Creating and Extracting Data From a Hash Table” on page 105 to parse the capacitance back annotation file and to store and retrieve the associated capacitance data. The capacitance back annotation file must contain
October 2000 |
109 |
Product Version 3.2 |
Back Annotation and Delay Calculation
Example Listings
cell output net names and their associated capacitance values. Figure 4-5 on page 47 shows an example file that adheres to this syntax.
Figure 5-7 Delay calculation: random cell scanning and capacitance values associated with cell output nets
#include "acc_user.h" #include "veriuser.h"
/*** System task invocation routine ***/
global dl_prim_invoke(); global dl_path_invoke(); global void dl_invoke();
/*** Main delay calculation routines ***/
local void dl_calc_prim_delays(); local void dl_calc_path_delays();
/*** Auxiliary routines ***/
local double dl_load_factor();
local double dl_estimate_capacitance(); local handle dl_handle_driving_prim();
/*** Argument processing routines ***/
local handle dl_process_scope_arg(); local bool dl_process_estimate_arg();
/*** Global variables ***/
bool dl_verbose_flag = false;
/*** Wire capacitance estimation table ***/
int wirecap_est_table_size = 10; double wirecap_est_table[] =
{1.2, 2.2, 3.4, 5.0, 6.7, 8.8, 10.2, 12.7, 15.3, 18.0};
#define dlPrim 1 #define dlPath 2
double dl_backan_fetch();
/***************************************************************/ /* System task invocation routines */ /***************************************************************/
/* |
DL_PRIM_INVOKE |
/* |
Begin delay calculation for primitive delay based models |
/***************************************************************/ exfunc dl_prim_invoke()
{
dl_invoke(dlPrim);
}
/***************************************************************/
/* |
DL_PATH_INVOKE |
/* |
Begin delay calculation for path delay based models |
/***************************************************************/ exfunc dl_path_invoke()
{
dl_invoke(dlPath);
}
/***************************************************************/
October 2000 |
110 |
Product Version 3.2 |
|
|
Back Annotation and Delay Calculation |
|
|
|
Example Listings |
|
|
|
|
|
/* |
DL_INVOKE |
*/ |
|
/* |
This routine invokes delay calculation processing. |
*/ |
|
/* |
It accepts an argument indicating whether to begin path |
*/ |
|
/* |
delay |
or primitive delay-based calculations |
*/ |
/* |
This routine performs the following functions: |
*/ |
|
/* |
> |
Initialize and configure the access routines. |
*/ |
/* |
> |
Process command line plusargs |
*/ |
/* |
> |
Call routines to process system task arguments |
*/ |
/* |
> |
Call routine to calculate interconnect delays |
*/ |
/***************************************************************/ exfunc void dl_invoke(prim_or_path)
int prim_or_path;
{
handle dl_scope_g; int mtmparam; handle scope;
bool estimate_flag;
acc_initialize(); acc_configure(accDevelopmentVersion,"1.5a"); acc_configure(accToHiZDelay,"average"); acc_configure(accPathDelayCount,"2"); acc_configure(accDefaultAttr0,"true");
/************************************************************/ /* If "+dlverbose" appears on command line, set global flag */ /************************************************************/ if (mc_scan_plusargs("dlverbose"))
{
dl_verbose_flag = true;
if (prim_or_path == dlPrim)
io_printf("Delay calculation invoked for primitive ", "delay cells : \n");
else
io_printf("Delay calculation invoked for path delay cells : \n");
}
/********************************************************/
/*** |
Process argument to determine scope of delay |
***/ |
/*** |
calculation |
***/ |
/********************************************************/ scope = dl_process_scope_arg();
/******************************************************/ /*** Process argument to determine wire capacitance ***/
/*** estimation or back annotation ***/
/******************************************************/ estimate_flag = dl_process_estimate_arg();
/*************************************/ /*** Calculate interconnect delays ***/
/*************************************/ if (prim_or_path == dlPath)
dl_calc_path_delays(scope,estimate_flag); else
dl_calc_prim_delays(scope,estimate_flag); /*******************************************************/ /*** If necessary, free back-annotation table memory ***/
/*******************************************************/ if (!estimate_flag)
dl_free_backan_table();
October 2000 |
111 |
Product Version 3.2 |
Back Annotation and Delay Calculation
Example Listings
/******************/ /*** Aesthetics ***/
/******************/ if (dl_verbose_flag) io_printf("\n");
/***********************************/ /*** Access routine use complete ***/
/***********************************/ acc_close();
}
/***************************************************************/ /* Main delay calculation processing loops */ /***************************************************************/ /****************************************************************/
/*** DL_CALC_PRIM_DELAYS |
|
|
***/ |
|||
/*** This |
routine accepts |
a handle to |
a module, scans |
***/ |
||
/*** |
each |
offspring |
cell, |
and performs delay calculation and |
***/ |
|
/*** |
annotation for |
each output port. |
|
***/ |
/****************************************************************/ static void dl_calc_prim_delays(start_mod,estimate_flag)
handle |
start_mod; |
bool |
estimate_flag; |
{ |
|
handle |
mod, term, prim, driver; |
handle |
portout, portout_net, portout_term; |
int |
fanout_count; |
double |
fanout_load, wire_load; |
double |
rise_strength, fall_strength, rise, fall; |
/**********************************************************/ /*** Process each cell module instance within the scope ***/
/**********************************************************/ mod = null;
while (mod = acc_next_cell(start_mod, mod))
{
/****************************************************/ /*** Process each output port in this cell module ***/
/****************************************************/ portout = null;
while (portout = acc_next_portout(mod,portout))
{
/***********************************************/ /*** Process each net connected to this port ***/
/***********************************************/ portout_net = null;
while (portout_net = acc_next_loconn(portout,portout_net))
{
/*********************/ /*** Count fanouts ***/
/*********************/
fanout_count = acc_count(acc_next_cell_load,portout_net); if (estimate_flag && (fanout_count == 0))
continue;
/***********************************************/ /*** Determine loading on net due to fanouts ***/
/***********************************************/
October 2000 |
112 |
Product Version 3.2 |
Back Annotation and Delay Calculation
Example Listings
fanout_load = dl_load_factor(portout_net);
/********************************************************/ /*** Determine estimated or back-annotated wire ***/
/***capacitance ***/
/********************************************************/ if (estimate_flag)
wire_load = dl_estimate_capacitance(fanout_count); else
wire_load = dl_backan_fetch(portout_net);
/********************************************************/ /*** Determine attributes associated with portout_net ***/
/********************************************************/ rise_strength = acc_fetch_attribute(portout_net,
"RiseStrength$"); fall_strength = acc_fetch_attribute(portout_net,
"FallStrength$");
/***************************************/ /*** Calculate load dependent delays ***/
/***************************************/
rise = rise_strength * (fanout_load + wire_load); fall = fall_strength * (fanout_load + wire_load); /*************************************************/ /*** Scan the primitives which drive this port ***/
/*************************************************/ driver = null;
while (driver = acc_next_driver(portout_net,driver))
{
prim = acc_handle_parent(driver); if (acc_handle_parent(prim) != mod)
continue;
/*******************************************/ /*** Add calculated delays to the delays ***/
/*** on the driving primitive ***/
/*******************************************/ acc_append_delays(prim, rise, fall); /************************************************/ /*** If requested, print detailed calculation ***/
/************************************************/ if (dl_verbose_flag)
{
double newrise, newfall, newz; acc_fetch_delays(prim,&newrise,&newfall,&newz); io_printf("\nNet %s delays : rise = %6.2f fall =
%6.2f\n", acc_fetch_fullname(portout_net), newrise, newfall);
io_printf(" rise_strength =%6.2f fall_strength = %6.2f\n",rise_strength, fall_strength);
io_printf(" fanout_load = %6.2f wire_load = %6.2f\n", fanout_load, wire_load);
io_printf(" added rise = %6.2f added fall = %6.2f\n", rise, fall);
}
}
}
}
}
}
October 2000 |
113 |
Product Version 3.2 |
Back Annotation and Delay Calculation
Example Listings
/****************************************************************/
/* |
DL_CALC_PATH_DELAYS |
|
|
*/ |
||
/* |
This |
routine accepts |
a handle to a module, scans |
*/ |
||
/* |
each |
offspring |
cell, |
and |
performs delay calculation and |
*/ |
/* |
annotation for |
each path |
in the cell. |
*/ |
/****************************************************************/ static void dl_calc_path_delays(start_mod,estimate_flag)
handle |
start_mod; |
bool |
estimate_flag; |
{ |
|
handle |
mod, path; |
handle |
pathout_net; |
int |
fanout_count; |
double |
fanout_load, wire_load; |
double |
rise_strength, fall_strength, rise, fall; |
/**********************************************************/ /*** Process each cell module instance within the scope ***/
/**********************************************************/ mod = null;
while (mod = acc_next_cell(start_mod, mod))
{
/*********************************************/ /*** Process each path in this cell module ***/
/*********************************************/ path = null;
while (path = acc_next_modpath(mod,path))
{
/*********************/ /*** Count fanouts ***/
/*********************/
pathout_net = acc_handle_pathout(path);
fanout_count = acc_count(acc_next_cell_load,pathout_net); if (estimate_flag && (fanout_count == 0))
continue;
/***********************************************/ /*** Determine loading on net due to fanouts ***/
/***********************************************/ fanout_load = dl_load_factor(pathout_net);
/*********************************************************/
/*** |
Determine estimated or back-annotated wire |
***/ |
/*** |
capacitance |
***/ |
/*********************************************************/ if (estimate_flag)
wire_load = dl_estimate_capacitance(fanout_count); else
wire_load = dl_backan_fetch(pathout_net);
/*************************************************/ /*** Determine attributes associated with path ***/
/*************************************************/ rise_strength = acc_fetch_attribute(path, "RiseStrength$"); fall_strength = acc_fetch_attribute(path, "FallStrength$");
/***************************************/
/*** Calculate load dependent delays ***/
/***************************************/
rise = rise_strength * (fanout_load + wire_load);
October 2000 |
114 |
Product Version 3.2 |
Back Annotation and Delay Calculation
Example Listings
fall = fall_strength * (fanout_load + wire_load); /*****************************************/
/*** Append delays to the driving path ***/
/*****************************************/ acc_append_delays(path, rise, fall);
/**********************************************/ /*** Set pulse control to 100% x-generation ***/
/*** for new delay ***/
/**********************************************/ acc_set_pulsere(path,0.0,1.0);
/********************************************************/
/*** |
If requested, print detailed calculation |
***/ |
/*** |
information |
***/ |
/********************************************************/ if (dl_verbose_flag)
{
double newrise, newfall, newz; acc_fetch_delays(path,&newrise,&newfall,&newz); io_printf("\nPath %s delays : rise = %6.2f fall = %6.2f\n",
acc_fetch_fullname(path), newrise, newfall); io_printf(" rise_strength = %6.2f fall_strength =%6.2f\n",
rise_strength, fall_strength);
io_printf(" fanout_load = %6.2f wire_load = %6.2f\n", fanout_load, wire_load);
io_printf(" added rise = %6.2f added fall = %6.2f\n", rise, fall);
}
}
}
}
/****************************************************************/ /* Auxiliary routines */ /****************************************************************/
/* |
DL_LOAD_FACTOR |
*/ |
/* |
This routine accepts a pointer to a net, scans |
*/ |
/* |
its connected terminals, and returns the total load |
*/ |
/* |
factor on the net. This is determined by finding |
*/ |
/* |
specify parameters called FanoutLoad$netname associated |
*/ |
/* |
with each load and driver and summing their values. |
*/ |
/***************************************************************/ static double dl_load_factor(net)
handle net;
{
double total_lf = 0;
handle load, load_net, driver_prim, driver_mod, driver_net, driver;
/************************************/ /*** Process each cell input load ***/
/************************************/ load = null;
while (load = acc_next_cell_load(net,load))
{
/**************************************/ /*** Get net connected to this load ***/
/**************************************/ load_net = acc_handle_conn(load);
total_lf += acc_fetch_attribute(load_net, "FanoutLoad$");
}
October 2000 |
115 |
Product Version 3.2 |
Back Annotation and Delay Calculation
Example Listings
/*************************************************/ /*** If load has multiple drivers, scan fanin, ***/
/*** adding each lf to total_lf ***/
/*************************************************/ if (acc_count(acc_next_driver,net) > 1)
{
handle |
net_mod = acc_handle_parent(net); |
/*******************************/ |
/*** Process each net driver ***/ |
|
|
/*******************************/ |
|
|
driver |
= null; |
|
while (driver = acc_next_driver(net, driver))
{
/*****************************************************/ /*** Don’t include load factor of driving terminal ***/
/*****************************************************/ driver_prim = acc_handle_parent(driver);
driver_mod = acc_handle_parent(driver_prim); if (driver_mod == net_mod)
continue;
/****************************************/ /*** Get net connected to this driver ***/
/****************************************/ driver_net = acc_handle_conn(driver);
total_lf += acc_fetch_attribute(driver_net, "FanoutLoad$");
}
}
return (total_lf);
}
/***************************************************************/
/* |
DL_ESTIMATE_CAPACITANCE |
*/ |
/* |
This routine accepts an integer indicating the |
*/ |
/* |
fanout count on a net, and returns the estimated wire |
*/ |
/* |
capacitance from table wirecap_est_table (defined |
*/ |
/* |
earlier in this file). If the fanout count is larger |
*/ |
/* |
than the table allows, a warning is printed, and |
*/ |
/* |
the largest value in the table is returned. |
*/ |
/***************************************************************/ static double dl_estimate_capacitance(fanout_count)
int fanout_count;
{
if (fanout_count > wirecap_est_table_size)
{
io_printf("Warning from dl_estimate_capacitance : ", "excessive fanout\n");
fanout_count = wirecap_est_table_size;
}
return (wirecap_est_table[fanout_count-1]);
}
/*************************************************************/ /* Argument processing routines */ /*************************************************************/
/* |
DL_PROCESS_SCOPE_ARG |
*/ |
/* |
Process first argument: Full hierarchical name of |
*/ |
/* |
scope to which delay calculation will be performed. |
*/ |
/* |
This routine returns the scope indicated by the |
*/ |
/* |
first argument. If the first argument is null, |
*/ |
October 2000 |
116 |
Product Version 3.2 |
|
Back Annotation and Delay Calculation |
|
|
Example Listings |
|
|
|
|
/* |
the invoking module is returned as the scope. |
*/ |
/* |
If the first argument does not represent |
*/ |
/* |
a valid scope, the invoking module is returned |
*/ |
/* |
as the scope and an error is reported. This routine |
*/ |
/* |
uses some PLI "tf_" routines and defined values. |
*/ |
/*************************************************************/ static handle dl_process_scope_arg()
{
handle scope = acc_handle_tfarg(1); int arg_type;
if (acc_fetch_type(scope) != accModule)
{
/************************************************************/ /** if task argument is null, set scope to invoking module **/ /************************************************************/ arg_type = tf_typep(1);
if (arg_type == tf_nullparam)
scope = acc_handle_parent(tf_getinstance());
/***********************************************************/ /*** if task argument not null and is not a valid scope, ***/
/*** set scope to invoking module display error ***/
/***********************************************************/ else
{
scope = acc_handle_parent(tf_getinstance()); io_printf("%s%s","Warning from delay calculation :",
"invalid scope argument, setting scope to invoking module\n");
}
}
if (dl_verbose_flag)
io_printf(" Scope : %s\n", acc_fetch_fullname(scope));
return (scope);
}
/***************************************************************/
/* |
DL_PROCESS_ESTIMATE_ARG |
*/ |
/* |
Process second argument: estimate wire capacitance |
*/ |
/* |
or read from file. Return true to indicate estimated |
*/ |
/* |
capacitance, false to indicate back-annotated |
*/ |
/* |
capacitance. This routine uses various |
*/ |
/* |
PLI "tf_" routines and defined values. |
*/ |
/***************************************************************/ static bool dl_process_estimate_arg()
{ |
|
int |
arg_type = tf_typep(2); |
char |
*arg = (char *)tf_getp(2); |
char |
net_filename[256]; |
if (arg_type != tf_string)
{
io_printf("%s%s","Warning from delay calculation :", " invalid second argument, will estimate wire capacitance\n");
/*** return true to indicate estimated capacitance ***/
return (true);
}
if ((arg == null) || (strcmp(arg, "estimate") == 0))
{
October 2000 |
117 |
Product Version 3.2 |