- •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
if (dl_verbose_flag)
io_printf(" Wire capacitance will be estimated\n");
/*** return true to indicate estimated capacitance ***/
return (true);
}
else
{
if (dl_verbose_flag)
io_printf(" Wire capacitance file : \"%s\"\n", arg);
strcpy(net_filename, arg);
if (!dl_make_backan_table(net_filename))
{
io_printf(" Wire capacitance will be estimated\n"); return(true);
}
/*** return false to indicate back annotated capacitance ***/
return (false);
}
}
s_tfcell veriusertfs[] = {
{usertask,0,
0,0, dl_prim_invoke,0, "$dcalc_prim",1}, {usertask,0, 0,0, dl_path_invoke,0, "$dcalc_path",1}, 0} };
Random Cell Scan and Cell Interconnect Nets
Figure 5-8 on page 119 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 interconnect 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)
October 2000 |
118 |
Product Version 3.2 |
Back Annotation and Delay Calculation
Example Listings
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 Section “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 interconnect net names and their associated capacitance values. Figure 4-6 on page 47 shows an example file that adheres to this syntax.
Figure 5-8 Delay calculation: random cell scanning and capacitance values associated with interconnect 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_icn_delays(); local void dl_calc_path_icn_delays();
/*** Auxiliary routines ***/
local double dl_load_factor();
local double dl_estimate_capacitance(); local handle dl_handle_icn();
/*** 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 routine */ /***************************************************************/
/* |
DL_PRIM_INVOKE |
*/ |
/* |
Begin delay calculation for primitive delay based models |
*/ |
/***************************************************************/
October 2000 |
119 |
Product Version 3.2 |
Back Annotation and Delay Calculation
Example Listings
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);
}
/****************************************************************/
/* |
DL_INVOKE |
|
*/ |
/* |
This routine invokes delay calculation processing. |
*/ |
|
/* |
It accepts |
an argument which indicates 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();
October 2000 |
120 |
Product Version 3.2 |
Back Annotation and Delay Calculation
Example Listings
/*************************************/ /*** Calculate interconnect delays ***/
/*************************************/ if (prim_or_path == dlPath)
dl_calc_path_icn_delays(scope,estimate_flag); else
dl_calc_prim_icn_delays(scope,estimate_flag);
/*******************************************************/ /*** If necessary, free back-annotation table memory ***/
/*******************************************************/ if (!estimate_flag)
dl_free_backan_table(); /******************/ /*** Aesthetics ***/
/******************/ if (dl_verbose_flag) io_printf("\n");
/***********************************/ /*** Access routine use complete ***/
/***********************************/ acc_close();
}
/***************************************************************/ /* Main delay calculation processing loops */ /***************************************************************/
/* |
DL_CALC_PRIM_ICN_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_icn_delays(start_mod,estimate_flag)
handle |
start_mod; |
bool |
estimate_flag; |
{ |
|
handle |
mod, term, prim, driver; |
handle |
portout, portout_net, portout_term, interconnect_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 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;
October 2000 |
121 |
Product Version 3.2 |
Back Annotation and Delay Calculation
Example Listings
interconnect_net = null;
while (portout_net = acc_next_loconn(portout,portout_net))
{
/********************************************************/ /** If capacitance is back annotated, get interconnect **/
/** |
net for this output net - break out at first |
**/ |
/** |
unconnected bit |
**/ |
/********************************************************/ if (!estimate_flag)
{
interconnect_net = acc_next_hiconn(portout, interconnect_net);
if (interconnect_net == null) break;
}
/*********************/ /*** 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 ***/
/***********************************************/ fanout_load = dl_load_factor(portout_net);
/********************************************************/ /* Determine estimated or backannotated wire capacitance */ /********************************************************/ if (estimate_flag)
wire_load = dl_estimate_capacitance(fanout_count); else
wire_load = dl_backan_fetch(interconnect_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 that 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 ***/
/*******************************************/
October 2000 |
122 |
Product Version 3.2 |
Back Annotation and Delay Calculation
Example Listings
acc_append_delays(prim, rise, fall);
/******************************************************/ /* If requested, print detailed calculation information */ /******************************************************/ 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);
}
}
}
}
}
}
/***************************************************************/
/* |
DL_CALC_PATH_ICN_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_icn_delays(start_mod,estimate_flag)
handle |
start_mod; |
bool |
estimate_flag; |
{ |
|
handle |
mod, path; |
handle |
pathout_net, interconnect_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))
{
/*****************************/ /*** Get number of fanouts ***/
/*****************************/ pathout_net = acc_handle_pathout(path);
fanout_count = acc_count(acc_next_cell_load,pathout_net); if (estimate_flag && (fanout_count == 0))
continue;
if (!estimate_flag)
interconnect_net = dl_handle_icn(mod,pathout_net);
October 2000 |
123 |
Product Version 3.2 |
Back Annotation and Delay Calculation
Example Listings
/***********************************************/ /*** Determine loading on net due to fanouts ***/
/***********************************************/ fanout_load = dl_load_factor(pathout_net);
/*********************************************************/ /* Determine estimated or backannotated wire capacitance */ /*********************************************************/ if (estimate_flag)
wire_load = dl_estimate_capacitance(fanout_count); else
wire_load = dl_backan_fetch(interconnect_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); 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 */
October 2000 |
124 |
Product Version 3.2 |
|
Back Annotation and Delay Calculation |
|
|
Example Listings |
|
|
|
|
/* |
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$");
}
/*************************************************/ /*** 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);
}
/**************************************************************/
October 2000 |
125 |
Product Version 3.2 |
|
Back Annotation and Delay Calculation |
|
|
Example Listings |
|
|
|
|
/* |
DL_HANDLE_ICN |
*/ |
/* |
This routine accepts a handle to a scope and a net, |
*/ |
/* |
and returns the interconnect net (hiconn) that the |
*/ |
/* |
net is connected to. |
*/ |
/**************************************************************/ static handle dl_handle_icn(mod,cell_output_net)
handle mod, cell_output_net;
{
handle portout;
/*********************************************************/ /*** Scan output ports until the one fed by the net is ***/
/*** found, then return the hiconn net ***/
/*********************************************************/ portout = null;
while (portout = acc_next_portout(mod,portout))
{
if (acc_next_loconn(portout,null) == cell_output_net) return(acc_next_hiconn(portout,null));
}
/******************************************************/ /*** Print warning and return null if net not found ***/
/******************************************************/ io_printf("Warning from dl_handle_icn : ", "output net \"%s\" not
found\n", acc_fetch_fullname(cell_output_net)); return(null);
}
/****************************************************************/
/* |
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 is performed. This routine |
*/ |
/* |
returns the scope indicated by the first argument. If the |
*/ |
/* |
first argument is null, 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 |
*/ |
October 2000 |
126 |
Product Version 3.2 |
Back Annotation and Delay Calculation
Example Listings
/***************************************************************/ 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))
{
if (dl_verbose_flag)
io_printf(" Wire capacitance will be estimated\n");
/*** return true to indicate estimated capacitance ***/
return (true);
}
October 2000 |
127 |
Product Version 3.2 |