[14] | 1 | /**CFile*********************************************************************** |
---|
| 2 | |
---|
| 3 | FileName [spfdCmd.c] |
---|
| 4 | |
---|
| 5 | PackageName [spfd] |
---|
| 6 | |
---|
| 7 | Synopsis [Interface functions for commands spfd_pilo and spfd_pdlo.] |
---|
| 8 | |
---|
| 9 | Description [Interface functions for commands spfd_pilo and spfd_pdlo.] |
---|
| 10 | |
---|
| 11 | SeeAlso [spfdOpt.c] |
---|
| 12 | |
---|
| 13 | Author [Balakrishna Kumthekar] |
---|
| 14 | |
---|
| 15 | Copyright [This file was created at the University of Colorado at Boulder. |
---|
| 16 | The University of Colorado at Boulder makes no warranty about the suitability |
---|
| 17 | of this software for any purpose. It is presented on an AS IS basis.] |
---|
| 18 | |
---|
| 19 | ******************************************************************************/ |
---|
| 20 | |
---|
| 21 | #include "spfdInt.h" |
---|
| 22 | |
---|
| 23 | static char rcsid[] UNUSED = "$Id: spfdCmd.c,v 1.28 2002/09/09 01:04:28 fabio Exp $"; |
---|
| 24 | |
---|
| 25 | /*---------------------------------------------------------------------------*/ |
---|
| 26 | /* Constant declarations */ |
---|
| 27 | /*---------------------------------------------------------------------------*/ |
---|
| 28 | |
---|
| 29 | /*---------------------------------------------------------------------------*/ |
---|
| 30 | /* Type declarations */ |
---|
| 31 | /*---------------------------------------------------------------------------*/ |
---|
| 32 | |
---|
| 33 | |
---|
| 34 | /*---------------------------------------------------------------------------*/ |
---|
| 35 | /* Structure declarations */ |
---|
| 36 | /*---------------------------------------------------------------------------*/ |
---|
| 37 | |
---|
| 38 | |
---|
| 39 | /*---------------------------------------------------------------------------*/ |
---|
| 40 | /* Variable declarations */ |
---|
| 41 | /*---------------------------------------------------------------------------*/ |
---|
| 42 | |
---|
| 43 | static jmp_buf timeOutEnv; /* time out */ |
---|
| 44 | int spfdCreatedPart; /* Whether network BDDs were created in the package */ |
---|
| 45 | int spfdVerbose; /* verbosity */ |
---|
| 46 | float spfdAlpha; /* spfdAlpha * load + (1-spfdAlpha) * topDepth, is used to order |
---|
| 47 | fanin nodes during SPFD computation */ |
---|
| 48 | boolean spfdPerfSim; /* Perform simulation */ |
---|
| 49 | boolean spfdNtkChanged; /* TRUE if network changes structurally or functionally */ |
---|
| 50 | boolean spfdReprogNoWire; /* If TRUE, no functional changes are performed |
---|
| 51 | unless required by structural changes */ |
---|
| 52 | int spfdWiresAdded, spfdNumWiresRem; /* Number of wires added and removed */ |
---|
| 53 | int spfdSortNodes; /* Method to sort nodes */ |
---|
| 54 | int spfdMethod; /* Optimization method */ |
---|
| 55 | |
---|
| 56 | /*---------------------------------------------------------------------------*/ |
---|
| 57 | /* Macro declarations */ |
---|
| 58 | /*---------------------------------------------------------------------------*/ |
---|
| 59 | |
---|
| 60 | |
---|
| 61 | /**AutomaticStart*************************************************************/ |
---|
| 62 | |
---|
| 63 | /*---------------------------------------------------------------------------*/ |
---|
| 64 | /* Static function prototypes */ |
---|
| 65 | /*---------------------------------------------------------------------------*/ |
---|
| 66 | |
---|
| 67 | static int CommandSpfdNetworkOptimize(Hrc_Manager_t **hmgr, int argc, char **argv); |
---|
| 68 | static int CommandSpfdPlaceOptimize(Hrc_Manager_t **hmgr, int argc, char **argv); |
---|
| 69 | static void TimeOutHandle(void); |
---|
| 70 | static int TestIsNetworkMultipleValued(Ntk_Network_t *network); |
---|
| 71 | static int SpfdSimultaneousPlacementAndLogicOpt(Ntk_Network_t *network, char *netFile, char *archFile, char *placeFile, char *routeFile, char *netOutFile, int regionDepth); |
---|
| 72 | |
---|
| 73 | /**AutomaticEnd***************************************************************/ |
---|
| 74 | |
---|
| 75 | |
---|
| 76 | /*---------------------------------------------------------------------------*/ |
---|
| 77 | /* Definition of exported functions */ |
---|
| 78 | /*---------------------------------------------------------------------------*/ |
---|
| 79 | |
---|
| 80 | /**Function******************************************************************** |
---|
| 81 | |
---|
| 82 | Synopsis [This function initializes the spfd package.] |
---|
| 83 | |
---|
| 84 | SideEffects [None] |
---|
| 85 | |
---|
| 86 | SeeAlso [Spfd_End] |
---|
| 87 | |
---|
| 88 | ******************************************************************************/ |
---|
| 89 | void |
---|
| 90 | Spfd_Init(void) |
---|
| 91 | { |
---|
| 92 | Cmd_CommandAdd("spfd_pilo", CommandSpfdNetworkOptimize, 1); |
---|
| 93 | Cmd_CommandAdd("spfd_pdlo", CommandSpfdPlaceOptimize, 1); |
---|
| 94 | |
---|
| 95 | } /* End of Spfd_Init */ |
---|
| 96 | |
---|
| 97 | /**Function******************************************************************** |
---|
| 98 | |
---|
| 99 | Synopsis [This function ends the spfd package.] |
---|
| 100 | |
---|
| 101 | SideEffects [None] |
---|
| 102 | |
---|
| 103 | SeeAlso [Spfd_Init] |
---|
| 104 | |
---|
| 105 | ******************************************************************************/ |
---|
| 106 | void |
---|
| 107 | Spfd_End(void) |
---|
| 108 | { |
---|
| 109 | |
---|
| 110 | } /* End of Spfd_End */ |
---|
| 111 | |
---|
| 112 | /*---------------------------------------------------------------------------*/ |
---|
| 113 | /* Definition of internal functions */ |
---|
| 114 | /*---------------------------------------------------------------------------*/ |
---|
| 115 | |
---|
| 116 | |
---|
| 117 | /*---------------------------------------------------------------------------*/ |
---|
| 118 | /* Definition of static functions */ |
---|
| 119 | /*---------------------------------------------------------------------------*/ |
---|
| 120 | /**Function******************************************************************** |
---|
| 121 | |
---|
| 122 | Synopsis [Implements SPFD-based placement independent logic |
---|
| 123 | optimization command, spfd_pilo, for combinational circuits mapped |
---|
| 124 | to LUT-based FPGAs.] |
---|
| 125 | |
---|
| 126 | CommandName [spfd_pilo] |
---|
| 127 | |
---|
| 128 | CommandSynopsis [Perform SPFD-based placement independent logic |
---|
| 129 | optimization.] |
---|
| 130 | |
---|
| 131 | CommandArguments [\[-a <\[0,1\]>\] \[-D <depth>\] \[-f |
---|
| 132 | <file>\] \[-h\] \[-i <freq>\] \[-p <percent>\] |
---|
| 133 | \[-r\] \[-S <n>\] \[-t <sec>\] \[-v <n>\] |
---|
| 134 | \[-w <file>\] ] |
---|
| 135 | |
---|
| 136 | CommandDescription [This command performs SPFD-based wire |
---|
| 137 | removal/replacement and reprogramming of combinational circuits |
---|
| 138 | mapped to LUT-based FPGAs to reduce the number of wires and nodes |
---|
| 139 | in the circuit. The flexibilities in the circuit are represented by |
---|
| 140 | SPFDs. The following references explain in detail the theory behind |
---|
| 141 | SPFDs. |
---|
| 142 | |
---|
| 143 | <p>S. Yamashita, H. Sawada, and A. Nagoya. A new method to express |
---|
| 144 | functional permissibilities for LUT based FPGAs and its |
---|
| 145 | applications. In International Conference on Computer Aided Design, |
---|
| 146 | pages 254-261, 1996. |
---|
| 147 | |
---|
| 148 | <p>Subarnarekha Sinha and Robert K. Brayton. Implementation and use of |
---|
| 149 | SPFDs in optimizaing Boolean networks. In International Conference |
---|
| 150 | on Computer Aided Design, 1998. |
---|
| 151 | |
---|
| 152 | <p> Instead of computing the flexibilities for every node in the |
---|
| 153 | network at once, the algorithm computes the flexibilities for one |
---|
| 154 | cluster at a time. Working with clusters allows us to avoid the BDD |
---|
| 155 | explosion problem and hence, handle large circuits. The SPFDs are |
---|
| 156 | computed for the cluster and the cluster nodes are reprogrammed |
---|
| 157 | based on the flexibility derived. Switching activity is used to |
---|
| 158 | drive the choice of alternate function to be implemented at the |
---|
| 159 | node. In the absence of switching activity information, the |
---|
| 160 | function that can reduce support of the node can be chosen (not |
---|
| 161 | implemented). Currently, an arbitrary choice is made from the |
---|
| 162 | flexibilities provided by SPFDs. (-S 0, -S 2, and -S 4) |
---|
| 163 | |
---|
| 164 | <p> |
---|
| 165 | Before calling this command a network should be created for the |
---|
| 166 | design (use flatten_hierarchy) and MDD ids for every node in the |
---|
| 167 | network should be created (static_order -o all -n append, for |
---|
| 168 | example). Dynamic variable ordering (dvo -e sift) can be enabled |
---|
| 169 | to reduce BDD sizes. |
---|
| 170 | |
---|
| 171 | <p>Command options:<p> |
---|
| 172 | |
---|
| 173 | <dl> |
---|
| 174 | |
---|
| 175 | <dt> -a <alpha> |
---|
| 176 | <dd> A convex combination of switched |
---|
| 177 | capacitance (switching activity * fanout count, SWC) and topological |
---|
| 178 | depth is used to sort the fanin nodes during SPFD computation. alpha |
---|
| 179 | is between 0 and 1.0. The cost function is alpha*SWC + |
---|
| 180 | (1.0-alpha)*topDepth. The default value is 0.5. <p> |
---|
| 181 | |
---|
| 182 | <dt> -D <depth> |
---|
| 183 | <dd> A cluster is computed which includes nodes within the specified |
---|
| 184 | 'depth'. The default value is 1.<p> |
---|
| 185 | |
---|
| 186 | <dt> -f <file> |
---|
| 187 | <dd> File with simulation vectors. The file |
---|
| 188 | format is as below. The format is simple but strict and hence, few |
---|
| 189 | checks are made. |
---|
| 190 | <p> .i <code>c n d o e p f q g r h s i t j u k a l b m</code><br> |
---|
| 191 | .s <br> |
---|
| 192 | 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1 ; <br> |
---|
| 193 | 0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 1 0 0 0 0 1 ; <br> |
---|
| 194 | 0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 1 ; <br> |
---|
| 195 | 0 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 0 1 ; <br> |
---|
| 196 | |
---|
| 197 | <p>The .i statement specifies the primary inputs of the network. The |
---|
| 198 | patterns start after .s key word. Each vector is a space separated list of |
---|
| 199 | bits and ends in a semi-colon. The length of any vector should be equal |
---|
| 200 | to the number of signals specified in the .i statement. A line starting |
---|
| 201 | with # is a comment. <p> |
---|
| 202 | |
---|
| 203 | <dt> -h |
---|
| 204 | <dd> Print usage. <p> |
---|
| 205 | |
---|
| 206 | <dt> -i <freq> |
---|
| 207 | <dd> Number of iterations after which to update node switching |
---|
| 208 | activity. This is valid only if patterns are provided in a file |
---|
| 209 | using -f option. The default value is every 5 iterations. <p> |
---|
| 210 | |
---|
| 211 | <dt> -m <n> |
---|
| 212 | <dd> Heuristics to optimize a selected node. <br> |
---|
| 213 | <code>0</code>: Reduce the selected node's support. <br> |
---|
| 214 | <code>1</code>: Reprogram the selected node.<br> |
---|
| 215 | <code>2</code>: Reprogram the selected node's fanin nodes. |
---|
| 216 | (default)<br> |
---|
| 217 | <code>3</code>: Reduce the selected node's fanout wires. <p> |
---|
| 218 | |
---|
| 219 | <dt> -p <percent> |
---|
| 220 | <dd> The percentage of vectors, specified via <code>-f</code> |
---|
| 221 | option, used to perform simulation (to update switching activity) |
---|
| 222 | during logic optimization. The default value is 10%. <p> |
---|
| 223 | |
---|
| 224 | <dt> -r |
---|
| 225 | <dd> Do not reprogram LUTs if no structural changes have been |
---|
| 226 | performed with in the cluster, i.e., if no nodes or wires have been |
---|
| 227 | removed do not change the local implementation of LUTs even if |
---|
| 228 | alternate implementations are availabe from SPFD information. The |
---|
| 229 | default is to reprogram. <p> |
---|
| 230 | |
---|
| 231 | <dt> -S <n> |
---|
| 232 | <dd> Method used to sort nodes. The nodes are then optimized in |
---|
| 233 | that order.<br> |
---|
| 234 | <code>0</code>: Random node is chosen. (default) <br> |
---|
| 235 | <code>1</code>: If switching activity is available, node with |
---|
| 236 | maximum SWC is chosen. <br> |
---|
| 237 | <code>2</code>: Node with maximum fanout is chosen. <br> |
---|
| 238 | <code>3</code>: If switching activity is available, node with |
---|
| 239 | minimum SWC is chosen. <br> |
---|
| 240 | <code>4</code>: Node with minimum fanout is chosen. <p> |
---|
| 241 | |
---|
| 242 | <dt> -t <sec> |
---|
| 243 | <dd> Time in seconds allowed to complete the command. If the |
---|
| 244 | computation time goes above that limit, the process is aborted. |
---|
| 245 | The default is no limit.<p> |
---|
| 246 | |
---|
| 247 | <dt> -v <n> |
---|
| 248 | <dd> Verbosity level. Default value is 0.<p> |
---|
| 249 | |
---|
| 250 | <dt> -w <file> |
---|
| 251 | <dd> File to output final optimized circuit. <p> ] |
---|
| 252 | </dl> |
---|
| 253 | |
---|
| 254 | <p> <b>Relevant flags to be set by the set command:</b> <p> |
---|
| 255 | <dl> |
---|
| 256 | <dt> <b>spfd_repl_rem</b> |
---|
| 257 | <dd> If <b>no</b>, the logic optimization performs only wire |
---|
| 258 | removal. If <b>yes</b>, both wire replacement and removal are performed. |
---|
| 259 | </dl> |
---|
| 260 | |
---|
| 261 | SideEffects [The network is changed to reflect the wires/nodes |
---|
| 262 | removed or replaced. The internal function of the nodes is also |
---|
| 263 | changed. The partition attached to the network is changed |
---|
| 264 | accordingly.] |
---|
| 265 | |
---|
| 266 | ******************************************************************************/ |
---|
| 267 | static int |
---|
| 268 | CommandSpfdNetworkOptimize( |
---|
| 269 | Hrc_Manager_t **hmgr, |
---|
| 270 | int argc, |
---|
| 271 | char **argv) |
---|
| 272 | { |
---|
| 273 | |
---|
| 274 | Ntk_Network_t *network = NIL(Ntk_Network_t); |
---|
| 275 | graph_t *simPart; |
---|
| 276 | int status,percent,frequency,regionDepth; |
---|
| 277 | int c; |
---|
| 278 | long timeOutPeriod,initialTime,finalTime; |
---|
| 279 | char *simFile,*writeFile; |
---|
| 280 | char endPtr[128]; |
---|
| 281 | FILE *fp = NIL(FILE); |
---|
| 282 | |
---|
| 283 | /* These are the default values. */ |
---|
| 284 | spfdCreatedPart = 0; /* Do not create a new partition */ |
---|
| 285 | timeOutPeriod = 0; |
---|
| 286 | simFile = NIL(char); /* File containing simulation vectors */ |
---|
| 287 | spfdVerbose = 0; /* verbosity */ |
---|
| 288 | regionDepth = 1; /* Depth of cluster */ |
---|
| 289 | percent = 10; /* Percent of total vectors to be simulated during opt. */ |
---|
| 290 | frequency = 5; /* Perform simulation every frequency iterations */ |
---|
| 291 | spfdSortNodes = RANDOM; /* Choose a random node for optimization */ |
---|
| 292 | spfdMethod = 2; |
---|
| 293 | spfdAlpha = 0.5; |
---|
| 294 | writeFile = NIL(char); /* File to output final optimized ckt. */ |
---|
| 295 | spfdNtkChanged = FALSE; |
---|
| 296 | spfdReprogNoWire = TRUE; |
---|
| 297 | spfdWiresAdded = 0; |
---|
| 298 | spfdNumWiresRem = 0; |
---|
| 299 | spfdPerfSim = FALSE; /* Default */ |
---|
| 300 | |
---|
| 301 | if (bdd_get_package_name() != CUDD) { |
---|
| 302 | (void) fprintf(vis_stderr, |
---|
| 303 | "** spfd error: The spfd package can be used " |
---|
| 304 | "only with CUDD package\n"); |
---|
| 305 | (void) fprintf(vis_stderr, |
---|
| 306 | "** spfd error: Please link with CUDD package\n"); |
---|
| 307 | return 0; |
---|
| 308 | } |
---|
| 309 | |
---|
| 310 | util_getopt_reset(); |
---|
| 311 | |
---|
| 312 | while((c = util_getopt(argc, argv, "a:D:f:hi:m:p:rS:t:v:w:")) != EOF) { |
---|
| 313 | switch(c) { |
---|
| 314 | case 'a': |
---|
| 315 | spfdAlpha = (float) strtod(util_optarg,(char **)&endPtr); |
---|
| 316 | if (!strcmp(util_optarg,endPtr)) { |
---|
| 317 | (void) fprintf(vis_stdout, |
---|
| 318 | "** spfd warning: Invalid value <%s> specified for -a\n", |
---|
| 319 | util_optarg); |
---|
| 320 | (void) fprintf(vis_stdout,"** spfd warning: Assuming 0.5.\n"); |
---|
| 321 | spfdAlpha = 0.5; |
---|
| 322 | } else if (spfdAlpha > 1.0 || spfdAlpha < 0.0) { |
---|
| 323 | (void) fprintf(vis_stdout, |
---|
| 324 | "** spfd warning: Value for -a <%f> not in [0,1]\n", |
---|
| 325 | spfdAlpha); |
---|
| 326 | (void) fprintf(vis_stdout,"** spfd warning: Assuming 0.5.\n"); |
---|
| 327 | spfdAlpha = 0.5; |
---|
| 328 | } |
---|
| 329 | break; |
---|
| 330 | case 'D': |
---|
| 331 | regionDepth = atoi(util_optarg); |
---|
| 332 | break; |
---|
| 333 | case 'f': |
---|
| 334 | if (!util_optarg) { |
---|
| 335 | (void) fprintf(vis_stderr, |
---|
| 336 | "** spfd error: Simulation file not specified.\n"); |
---|
| 337 | goto usage; |
---|
| 338 | } else { |
---|
| 339 | simFile = util_strsav(util_optarg); |
---|
| 340 | if ((fp = Cmd_FileOpen(simFile,"r",NIL(char *),1)) == NIL(FILE)) { |
---|
| 341 | (void) fprintf(vis_stderr, |
---|
| 342 | "** spfd error: Could not open %s for reading.\n", |
---|
| 343 | simFile); |
---|
| 344 | goto endgame; |
---|
| 345 | } else { |
---|
| 346 | fclose(fp); |
---|
| 347 | } |
---|
| 348 | spfdPerfSim = TRUE; |
---|
| 349 | } |
---|
| 350 | break; |
---|
| 351 | case 'h': |
---|
| 352 | goto usage; |
---|
| 353 | case 'i': |
---|
| 354 | frequency = atoi(util_optarg); |
---|
| 355 | break; |
---|
| 356 | case 'm': |
---|
| 357 | spfdMethod = atoi(util_optarg); |
---|
| 358 | if (spfdMethod > 3 || spfdMethod < 0) { |
---|
| 359 | (void) fprintf(vis_stderr, "** spfd warning: -m has invalid argument\n"); |
---|
| 360 | (void) fprintf(vis_stderr, "** spfd warning: Using 2 instead.\n"); |
---|
| 361 | } |
---|
| 362 | break; |
---|
| 363 | case 'p': |
---|
| 364 | percent = atoi(util_optarg); |
---|
| 365 | if (percent > 100 || percent < 0) { |
---|
| 366 | (void) fprintf(vis_stderr, |
---|
| 367 | "** spfd warning: -p <%d> has invalid argument.\n", |
---|
| 368 | percent); |
---|
| 369 | (void) fprintf(vis_stderr, |
---|
| 370 | "** spfd warning: Using 10%% instead.\n"); |
---|
| 371 | } |
---|
| 372 | break; |
---|
| 373 | case 'r': |
---|
| 374 | spfdReprogNoWire = FALSE; |
---|
| 375 | break; |
---|
| 376 | case 'S': |
---|
| 377 | spfdSortNodes = atoi(util_optarg); |
---|
| 378 | if (spfdSortNodes > 4 || spfdSortNodes < 0) { |
---|
| 379 | (void) fprintf(vis_stderr, |
---|
| 380 | "** spfd warning: -S <%d> has invalid argument.\n", |
---|
| 381 | spfdSortNodes); |
---|
| 382 | (void) fprintf(vis_stderr, |
---|
| 383 | "** spfd warning: Using 0 (random) instead.\n"); |
---|
| 384 | } |
---|
| 385 | break; |
---|
| 386 | case 't': |
---|
| 387 | timeOutPeriod = atoi(util_optarg); |
---|
| 388 | break; |
---|
| 389 | case 'v': |
---|
| 390 | spfdVerbose = atoi(util_optarg); |
---|
| 391 | break; |
---|
| 392 | case 'w': |
---|
| 393 | writeFile = util_strsav(util_optarg); |
---|
| 394 | if ((fp = Cmd_FileOpen(writeFile,"w",NIL(char *),1)) == NIL(FILE)) { |
---|
| 395 | (void) fprintf(vis_stderr, |
---|
| 396 | "** spfd error: Could not open %s for writing.\n", |
---|
| 397 | writeFile); |
---|
| 398 | goto endgame; |
---|
| 399 | } else { |
---|
| 400 | fclose(fp); |
---|
| 401 | } |
---|
| 402 | break; |
---|
| 403 | default: |
---|
| 404 | goto usage; |
---|
| 405 | } |
---|
| 406 | } |
---|
| 407 | |
---|
| 408 | if(Hrc_ManagerReadCurrentNode(*hmgr) == NIL(Hrc_Node_t)) { |
---|
| 409 | (void) fprintf(vis_stderr,"** spfd error: The hierarchy manager is empty." |
---|
| 410 | " Read in design.\n"); |
---|
| 411 | goto endgame; |
---|
| 412 | } |
---|
| 413 | |
---|
| 414 | network = (Ntk_Network_t *) |
---|
| 415 | Hrc_NodeReadApplInfo(Hrc_ManagerReadCurrentNode(*hmgr), |
---|
| 416 | NTK_HRC_NODE_APPL_KEY); |
---|
| 417 | |
---|
| 418 | if(network == NIL(Ntk_Network_t)) { |
---|
| 419 | (void) fprintf(vis_stderr,"** spfd error: There is no network. "); |
---|
| 420 | (void) fprintf(vis_stderr,"Use flatten_hierarchy.\n"); |
---|
| 421 | goto endgame; |
---|
| 422 | } |
---|
| 423 | |
---|
| 424 | /* Check if the current network has signals with multiple values. */ |
---|
| 425 | if (TestIsNetworkMultipleValued(network)) { |
---|
| 426 | (void) fprintf(vis_stderr,"** spfd error: Circuit has multiple " |
---|
| 427 | "valued variables.\n"); |
---|
| 428 | (void) fprintf(vis_stderr,"** spfd error: The algorithm currently " |
---|
| 429 | "supports only Boolean valued variables.\n"); |
---|
| 430 | goto endgame; |
---|
| 431 | } |
---|
| 432 | |
---|
| 433 | if(Ntk_NetworkReadNumPrimaryInputs(network) != |
---|
| 434 | Ntk_NetworkReadNumInputs(network)) { |
---|
| 435 | (void) fprintf(vis_stderr,"** spfd error: Pseudo inputs present " |
---|
| 436 | "in the network.\n"); |
---|
| 437 | (void) fprintf(vis_stderr,"** spfd error: The algorithm does not apply.\n"); |
---|
| 438 | goto endgame; |
---|
| 439 | } |
---|
| 440 | |
---|
| 441 | if(Ntk_NetworkReadNumLatches(network) > 0) { |
---|
| 442 | (void) fprintf(vis_stderr,"** spfd error: Sequential circuit.\n"); |
---|
| 443 | (void) fprintf(vis_stderr,"** spfd error: The command is only for combinational circuits.\n"); |
---|
| 444 | goto endgame; |
---|
| 445 | } |
---|
| 446 | |
---|
| 447 | /* Access a 'total' partition */ |
---|
| 448 | simPart = (graph_t *) Ntk_NetworkReadApplInfo(network,PART_NETWORK_APPL_KEY); |
---|
| 449 | if (simPart == NIL(graph_t) || |
---|
| 450 | (Part_PartitionReadMethod(simPart) != Part_Total_c)) { |
---|
| 451 | simPart = Part_NetworkCreatePartition(network, |
---|
| 452 | NIL(Hrc_Node_t), |
---|
| 453 | "dummy", (lsList) 0, |
---|
| 454 | (lsList) 0, NIL(mdd_t), |
---|
| 455 | Part_Total_c, |
---|
| 456 | (lsList) 0, |
---|
| 457 | FALSE, FALSE, TRUE); |
---|
| 458 | if (simPart == NIL(graph_t)) { |
---|
| 459 | (void) fprintf(vis_stderr,"** spfd error: Could not create partition.\n"); |
---|
| 460 | goto endgame; |
---|
| 461 | } |
---|
| 462 | Ntk_NetworkAddApplInfo(network,PART_NETWORK_APPL_KEY, |
---|
| 463 | (Ntk_ApplInfoFreeFn)Part_PartitionFreeCallback, |
---|
| 464 | (void *)simPart); |
---|
| 465 | spfdCreatedPart = 1; /* Using new partition */ |
---|
| 466 | (void) fprintf(vis_stdout, |
---|
| 467 | "** spfd info: A new partition created.\n"); |
---|
| 468 | } |
---|
| 469 | |
---|
| 470 | /* Start the timer.*/ |
---|
| 471 | if (timeOutPeriod > 0){ |
---|
| 472 | (void) signal(SIGALRM, (void(*)(int))TimeOutHandle); |
---|
| 473 | (void) alarm(timeOutPeriod); |
---|
| 474 | if (setjmp(timeOutEnv) > 0) { |
---|
| 475 | (void) fprintf(vis_stderr, "** spfd warning: Timeout occurred after "); |
---|
| 476 | (void) fprintf(vis_stderr, "%ld seconds.\n", timeOutPeriod); |
---|
| 477 | alarm(0); |
---|
| 478 | goto endgame; |
---|
| 479 | } |
---|
| 480 | } |
---|
| 481 | |
---|
| 482 | initialTime = util_cpu_time(); |
---|
| 483 | |
---|
| 484 | if (!spfdPerfSim) { |
---|
| 485 | (void) fprintf(vis_stdout, |
---|
| 486 | "** spfd info: Simulation vectors not specified.\n"); |
---|
| 487 | if (spfdSortNodes == MAXSWCAP) { |
---|
| 488 | (void) fprintf(vis_stdout, |
---|
| 489 | "** spfd info: Using method -S 2 instead of -S 1\n"); |
---|
| 490 | spfdSortNodes = MAXFANOUT; |
---|
| 491 | } else if (spfdSortNodes == MINSWCAP) { |
---|
| 492 | (void) fprintf(vis_stdout, |
---|
| 493 | "** spfd info: Using method -S 4 instead of -S 3\n"); |
---|
| 494 | spfdSortNodes = MINFANOUT; |
---|
| 495 | } |
---|
| 496 | } |
---|
| 497 | status = SpfdNetworkOptimize(network,simFile,percent,frequency,regionDepth); |
---|
| 498 | |
---|
| 499 | finalTime = util_cpu_time(); |
---|
| 500 | if(status) { |
---|
| 501 | (void) fprintf(vis_stdout, "%-20s%10ld\n", "** spfd info: analysis time =", |
---|
| 502 | (finalTime-initialTime)/1000); |
---|
| 503 | } |
---|
| 504 | else { |
---|
| 505 | (void) fprintf(vis_stdout, "** spfd error: Optimization failed.\n"); |
---|
| 506 | } |
---|
| 507 | |
---|
| 508 | if (writeFile) { |
---|
| 509 | SpfdNetworkWriteBlifFile(network,writeFile); |
---|
| 510 | FREE(writeFile); |
---|
| 511 | } |
---|
| 512 | |
---|
| 513 | if (simFile) |
---|
| 514 | FREE(simFile); |
---|
| 515 | |
---|
| 516 | if (spfdCreatedPart) |
---|
| 517 | Ntk_NetworkFreeApplInfo(network,PART_NETWORK_APPL_KEY); |
---|
| 518 | |
---|
| 519 | alarm(0); |
---|
| 520 | return 0; /* normal exit */ |
---|
| 521 | |
---|
| 522 | endgame: |
---|
| 523 | /* Clean up */ |
---|
| 524 | if (simFile) |
---|
| 525 | FREE(simFile); |
---|
| 526 | |
---|
| 527 | if (writeFile) |
---|
| 528 | FREE(writeFile); |
---|
| 529 | |
---|
| 530 | if (spfdCreatedPart) |
---|
| 531 | Ntk_NetworkFreeApplInfo(network,PART_NETWORK_APPL_KEY); |
---|
| 532 | |
---|
| 533 | return 1; /* Error exit */ |
---|
| 534 | |
---|
| 535 | usage: |
---|
| 536 | |
---|
| 537 | (void) fprintf(vis_stderr, "\nusage: Also see \'help spfd_pilo\' for more details.\n\n"); |
---|
| 538 | (void) fprintf(vis_stderr, " -a <alpha>\t\t<alpha> should be between 0.0 and 1.0\n"); |
---|
| 539 | (void) fprintf(vis_stderr, " \t\talpha*(SA*numFanout) + (1.0-alpha)*top_depth is used\n"); |
---|
| 540 | (void) fprintf(vis_stderr, " \t\tto order nodes during SPFD computation.\n"); |
---|
| 541 | (void) fprintf(vis_stderr, " \t\tSA is the switching activity of the node.\n"); |
---|
| 542 | (void) fprintf(vis_stderr, " \t\tThe default value is 0.5.\n\n"); |
---|
| 543 | (void) fprintf(vis_stderr, " -D <depth>\t\tCollect nodes that are within the specified depth.\n"); |
---|
| 544 | (void) fprintf(vis_stderr, " \t\tfrom the node being optimized.\n"); |
---|
| 545 | (void) fprintf(vis_stderr, " \t\tThe default is 1.\n\n"); |
---|
| 546 | (void) fprintf(vis_stderr, " -f <filename>\tFile containing simulation vectors.\n"); |
---|
| 547 | (void) fprintf(vis_stderr, " \t\tSee help for the format.\n\n"); |
---|
| 548 | (void) fprintf(vis_stderr, " -h \t\tCommand usage.\n\n"); |
---|
| 549 | (void) fprintf(vis_stderr, " -i <freq> \t\tPerform internal simulations after \n"); |
---|
| 550 | (void) fprintf(vis_stderr, " \t\tevery <freq> iterations.\n"); |
---|
| 551 | (void) fprintf(vis_stderr, " \t\tDefault is 5.\n\n"); |
---|
| 552 | (void) fprintf(vis_stderr, " -m <n> \t\tHeuristics to optimize a selected node:\n"); |
---|
| 553 | (void) fprintf(vis_stderr, " \t\t0: Reduce the selected node's support.\n"); |
---|
| 554 | (void) fprintf(vis_stderr, " \t\t1: Reprogram the selected node.\n"); |
---|
| 555 | (void) fprintf(vis_stderr, " \t\t2: Reprogram the selected node's fanin nodes. (default)\n"); |
---|
| 556 | (void) fprintf(vis_stderr, " \t\t3: Reduce the selected node's fanout wires.\n\n"); |
---|
| 557 | (void) fprintf(vis_stderr, " -p <percent>\tPercent of total pattern vectors that\n"); |
---|
| 558 | (void) fprintf(vis_stderr, " \t\tshould be used during internal simulations.\n"); |
---|
| 559 | (void) fprintf(vis_stderr, " \t\tDefault is 10%%.\n\n"); |
---|
| 560 | (void) fprintf(vis_stderr, " -r \t\tDo not reprogram internal nodes if the network\n"); |
---|
| 561 | (void) fprintf(vis_stderr, " \t\thas not changed structurally.\n"); |
---|
| 562 | (void) fprintf(vis_stderr, " \t\tBy default, reprogram.\n\n"); |
---|
| 563 | (void) fprintf(vis_stderr, " -S <value> \t\tHeuristic to select nodes for optimization.\n"); |
---|
| 564 | (void) fprintf(vis_stderr, " \t\t0. Random node. (default) \n"); |
---|
| 565 | (void) fprintf(vis_stderr, " \t\t1. Node with max. SA*numFanout.\n"); |
---|
| 566 | (void) fprintf(vis_stderr, " \t\t2. Node with max. fanout.\n"); |
---|
| 567 | (void) fprintf(vis_stderr, " \t\t3. Node with min. SA*numFanout.\n"); |
---|
| 568 | (void) fprintf(vis_stderr, " \t\t4. Node with min. fanout.\n\n"); |
---|
| 569 | (void) fprintf(vis_stderr, " -t <N> \t\tTime (s) limit for the command.\n\n"); |
---|
| 570 | (void) fprintf(vis_stderr, " -v <N> \t\tVerbosity level.\n\n"); |
---|
| 571 | (void) fprintf(vis_stderr, " -w <filename>\tFile to output final optimized circuit.\n\n"); |
---|
| 572 | (void) fprintf(vis_stderr, "set options: \n"); |
---|
| 573 | (void) fprintf(vis_stderr, "\tspfd_repl_rem <yes|no>\n"); |
---|
| 574 | (void) fprintf(vis_stderr, "\t\tReplace and remove wires simultaneously?\n"); |
---|
| 575 | return 1; /* error exit */ |
---|
| 576 | |
---|
| 577 | } /* End of CommandSpfdNetworkOptimize */ |
---|
| 578 | |
---|
| 579 | |
---|
| 580 | /**Function******************************************************************** |
---|
| 581 | |
---|
| 582 | Synopsis [Implements SPFD-based simultaneous placement and logic |
---|
| 583 | optimization command, spfd_pdlo, for combinational circuits mapped |
---|
| 584 | to LUT-based FPGAs.] |
---|
| 585 | |
---|
| 586 | CommandName [spfd_pdlo] |
---|
| 587 | |
---|
| 588 | CommandSynopsis [Perform SPFD-based simultaneous placement and |
---|
| 589 | logic optimization.] |
---|
| 590 | |
---|
| 591 | CommandArguments [\[-D <depth>\] \[-h\] \[-n <file>\] |
---|
| 592 | \[-r\] \[-t <sec>\] \[-v <n>\] \[-w <file>\] |
---|
| 593 | net_file arch_file place_file route_file] |
---|
| 594 | |
---|
| 595 | CommandDescription [This command performs SPFD-based combined logic |
---|
| 596 | and placement optimization of combinational circuits mapped to |
---|
| 597 | LUT-based FPGAs to improve circuit area and speed. The |
---|
| 598 | flexibilities in the circuit are represented by SPFDs. The |
---|
| 599 | following references explain in detail the theory behind SPFDs. |
---|
| 600 | |
---|
| 601 | <p>S. Yamashita, H. Sawada, and A. Nagoya. A new method to express |
---|
| 602 | functional permissibilities for LUT based FPGAs and its |
---|
| 603 | applications. In International Conference on Computer Aided Design, |
---|
| 604 | pages 254-261, 1996. |
---|
| 605 | |
---|
| 606 | <p>Subarnarekha Sinha and Robert K. Brayton. Implementation and use of |
---|
| 607 | SPFDs in optimizaing Boolean networks. In International Conference |
---|
| 608 | on Computer Aided Design, 1998. |
---|
| 609 | |
---|
| 610 | <p>The command implements a technique that tightly links the logic |
---|
| 611 | and placement optimization steps. The algorithm is based on |
---|
| 612 | simulated annealing. Two types of moves, directed towards global |
---|
| 613 | reduction in the cost function (total wire length), are accepted by |
---|
| 614 | the simulated annealing algorithm: (1) wire removal/replacement, |
---|
| 615 | and (2) swapping of a pair of blocks in the FPGA. Feedback from |
---|
| 616 | placement is valuable in making an informed choice of a target wire |
---|
| 617 | during logic optimization moves. The logic optimization steps |
---|
| 618 | performed are similar to those of spfd_pilo, except that the |
---|
| 619 | placement information is now used instead of the fanout count. |
---|
| 620 | More information on this technique can be found in : |
---|
| 621 | |
---|
| 622 | <p>Balakrishna Kumthekar and Fabio Somenzi. Power and delay reduction |
---|
| 623 | via simultaneous logic and placement optimization in FPGAs. In Design, |
---|
| 624 | Automation and Test in Europe, 2000. |
---|
| 625 | |
---|
| 626 | <p>The command produces a placement file which is used by VPR for |
---|
| 627 | routing. |
---|
| 628 | |
---|
| 629 | <p>This command can be used only if VIS is linked with VPR 4.22 |
---|
| 630 | (Versatile Place and Route), the FPGA place and route tool <a |
---|
| 631 | href="http://www.eecg.toronto.edu/~vaughn/vpr/vpr.html"> VPR</a>, |
---|
| 632 | from the University of Toronto. Please follow the instructions |
---|
| 633 | provided in the release notes to use VPR with VIS. You can also |
---|
| 634 | contact kumtheka@avanticorp.com if you need more help. |
---|
| 635 | |
---|
| 636 | <p>Before calling this command a network should be created for the |
---|
| 637 | design (use flatten_hierarchy) and MDD ids for every node in the |
---|
| 638 | network should be created (static_order -o all -n append). Dynamic |
---|
| 639 | variable ordering (dvo -e sift) can be enabled to reduce BDD sizes. |
---|
| 640 | |
---|
| 641 | <p>Command options:<p> |
---|
| 642 | |
---|
| 643 | <dl> |
---|
| 644 | |
---|
| 645 | <dt> -D <depth> |
---|
| 646 | <dd> A cluster is computed which includes nodes within the specified |
---|
| 647 | 'depth'. The default value is 1.<p> |
---|
| 648 | |
---|
| 649 | <dt> -n <file> |
---|
| 650 | <dd> File to output the optimized circuit in VPR's .net format.<p> |
---|
| 651 | |
---|
| 652 | <dt> -r |
---|
| 653 | <dd> Do not reprogram LUTs if no structural changes have been |
---|
| 654 | performed with in the cluster, i.e., if no nodes or wires have been |
---|
| 655 | removed do not change the local implementation of LUTs even if |
---|
| 656 | alternate implementations are availabe from SPFD information. The |
---|
| 657 | default is to reprogram. <p> |
---|
| 658 | |
---|
| 659 | <dt> -t <sec> |
---|
| 660 | <dd> Time in seconds allowed to complete the command. If the |
---|
| 661 | computation time goes above that limit, the process is is aborted. |
---|
| 662 | The default is no limit.<p> |
---|
| 663 | |
---|
| 664 | <dt> -v <n> |
---|
| 665 | <dd> Verbosity level.<p> |
---|
| 666 | |
---|
| 667 | <dt> -w <file> |
---|
| 668 | <dd> File to output final optimized circuit. <p> |
---|
| 669 | </dl> |
---|
| 670 | |
---|
| 671 | <p> <b>The following is needed by VPR:</b> <p> |
---|
| 672 | <dl> |
---|
| 673 | <dt> <b>net_file</b> |
---|
| 674 | <dd> The description of the circuit in the .net format. Logic |
---|
| 675 | optimization uses the circuit described in .BLIF format whereas VPR |
---|
| 676 | needs the same circuit described in .net format. VPack (which comes |
---|
| 677 | with VPR) converts a .BLIF format into a .net format. <p> |
---|
| 678 | |
---|
| 679 | <dt> <b>arch_file</b> |
---|
| 680 | <dd> Architecture description file for FPGAs. More information can be |
---|
| 681 | found in VPR's manual. <p> |
---|
| 682 | |
---|
| 683 | <dt> <b>place_file</b> |
---|
| 684 | <dd> File to dump placement information. <p> |
---|
| 685 | |
---|
| 686 | <dt> <b>route_file</b> |
---|
| 687 | <dd> File to dump routing information. <p> |
---|
| 688 | |
---|
| 689 | <p> <b>Relevant flags to be set by the set command:</b> <p> |
---|
| 690 | <dl> |
---|
| 691 | <dt> <b>spfd_pdlo_logic_move_freq</b> "r1 m1 r2 m2 ..." |
---|
| 692 | <dd> Perform m1 logic moves whenever the rate of acceptance during |
---|
| 693 | simulated annealing is greater than or equal to r1, and so on. r1, |
---|
| 694 | r2, r3 ... should be monotonically decreasing, else the results would |
---|
| 695 | be unpredictable. 0 <= ri <= 1.0. For example: |
---|
| 696 | |
---|
| 697 | <p> <code>set spfd_pdlo_logic_move_freq "0.8 0 0.5 5 0.2 10"</code><p> |
---|
| 698 | |
---|
| 699 | In the above logic schedule, zero logic moves per temperature will |
---|
| 700 | be performed when the rate of acceptance is above 0.8, 5 logic |
---|
| 701 | moves between 0.8 and 0.5, 10 moves between 0.5 and 0.2. As no |
---|
| 702 | value is specified for acceptance rate close to 0.0, by default, 1 |
---|
| 703 | logic move per temperature will be performed. In this example it |
---|
| 704 | will be 1 logic move between 0.2 and 0.0. |
---|
| 705 | The quotes around the schedule are necessary.<p> |
---|
| 706 | |
---|
| 707 | <dt> <b>spfd_repl_rem</b> |
---|
| 708 | <dd> If <b>no</b>, the logic optimization performs only wire |
---|
| 709 | removal. If <b>yes</b>, both wire replacement and removal are performed. <p> |
---|
| 710 | |
---|
| 711 | <dt> <b>spfd_pdlo_timing</b> |
---|
| 712 | <dd> If set, use timing driven method to remove or replace wires on the |
---|
| 713 | critical path. If not set, use bounding box of the wires as the |
---|
| 714 | cost function.<p> |
---|
| 715 | |
---|
| 716 | <dt> <b>spfd_pdlo_timing_nodeorwire</b> |
---|
| 717 | <dd> Remove/replace all the wires belonging to the most critical |
---|
| 718 | net. If not set, attempt to remove/replace only the most critical |
---|
| 719 | wire. <p> |
---|
| 720 | |
---|
| 721 | <dt> <b>spfd_pdlo_out_crit_nets_first</b> |
---|
| 722 | <dd> Output the circuit in VPR's .net format with the nets |
---|
| 723 | appearing in the increasing order of their slack. If not set, the |
---|
| 724 | initial net order specified in the original circuit's .net file is |
---|
| 725 | used. The file is specified with <code>-n</code> option. This |
---|
| 726 | variable is valid only if <b>spfd_pdlo_timing</b> is set. <p> |
---|
| 727 | |
---|
| 728 | <dt> <b>spfd_pdlo_remap_clb_array</b> |
---|
| 729 | <dd> During logic optimization, due to the removal of nodes in the |
---|
| 730 | network, the current size of FPGA might be bigger than it is |
---|
| 731 | necessary. In such cases, if this variable is set, the size of the |
---|
| 732 | FPGA is reduced to fit the current logic network. <p> |
---|
| 733 | |
---|
| 734 | </dl> |
---|
| 735 | |
---|
| 736 | <p> <b>Relevant flags that are options to VPR:</b> |
---|
| 737 | <p> For detailed information on the following options please refer to |
---|
| 738 | the manual that accompanies VPR source distribution. |
---|
| 739 | <p> |
---|
| 740 | <dl> |
---|
| 741 | <dt><b> vpr_nodisp</b> |
---|
| 742 | <dt><b>vpr_fix_pins</b> |
---|
| 743 | <dt><b>vpr_nx</b> |
---|
| 744 | <dt><b>vpr_ny</b> |
---|
| 745 | <dt><b>vpr_fast</b> |
---|
| 746 | <dt><b>vpr_init_t</b> |
---|
| 747 | <dt><b>vpr_alpha_t</b> |
---|
| 748 | <dt><b>vpr_exit_t</b> |
---|
| 749 | <dt><b>vpr_inner_num</b> |
---|
| 750 | <dt><b>vpr_seet</b> |
---|
| 751 | <dt><b>vpr_place_cost_exp</b> |
---|
| 752 | <dt><b>vpr_place_chan_width</b> |
---|
| 753 | </dl> ] |
---|
| 754 | |
---|
| 755 | SideEffects [The network is changed to reflect the wires/nodes |
---|
| 756 | removed or replaced. The internal function of the nodes is also |
---|
| 757 | changed. The partition attached to the network is changed |
---|
| 758 | accordingly.] |
---|
| 759 | |
---|
| 760 | ******************************************************************************/ |
---|
| 761 | static int |
---|
| 762 | CommandSpfdPlaceOptimize( |
---|
| 763 | Hrc_Manager_t **hmgr, |
---|
| 764 | int argc, |
---|
| 765 | char **argv) |
---|
| 766 | { |
---|
| 767 | |
---|
| 768 | #ifndef USE_VPR |
---|
| 769 | (void) fprintf(vis_stdout,"** spfd info: This command requires VPR " |
---|
| 770 | "(Versatile Place and Route)\n"); |
---|
| 771 | (void) fprintf(vis_stdout,"** spfd info: See \'help spfd_pdlo\' for more " |
---|
| 772 | "information\n"); |
---|
| 773 | (void) fprintf(vis_stdout,"** spfd info: on how to compile VIS with VPR.\n"); |
---|
| 774 | (void) fprintf(vis_stdout,"** spfd info: Exiting calmly ...\n"); |
---|
| 775 | return 0; |
---|
| 776 | #else |
---|
| 777 | |
---|
| 778 | Ntk_Network_t *network; |
---|
| 779 | graph_t *simPart; |
---|
| 780 | int status,regionDepth; |
---|
| 781 | int c; |
---|
| 782 | long timeOutPeriod,initialTime,finalTime; |
---|
| 783 | char *writeFile; |
---|
| 784 | char *netFile,*archFile,*placeFile,*routeFile; |
---|
| 785 | char *netOutFile; |
---|
| 786 | FILE *fp = NIL(FILE); |
---|
| 787 | |
---|
| 788 | |
---|
| 789 | /* These are the default values. */ |
---|
| 790 | spfdCreatedPart = 0; /* Do not create a new partition */ |
---|
| 791 | timeOutPeriod = 0; |
---|
| 792 | spfdVerbose = 0; /* verbosity */ |
---|
| 793 | regionDepth = 1; /* Depth of cluster */ |
---|
| 794 | writeFile = NIL(char); /* File to output final optimized ckt. */ |
---|
| 795 | spfdNtkChanged = FALSE; |
---|
| 796 | spfdReprogNoWire = TRUE; |
---|
| 797 | netFile = archFile = NIL(char); /* Circuit specified in VPR's .net |
---|
| 798 | format and FPGA architecture file */ |
---|
| 799 | placeFile = routeFile = NIL(char); /* File to store placement and |
---|
| 800 | routing information */ |
---|
| 801 | spfdWiresAdded = 0; |
---|
| 802 | spfdNumWiresRem = 0; |
---|
| 803 | netOutFile = NIL(char); /* File to output the optimized circuit in |
---|
| 804 | .net format */ |
---|
| 805 | status = FALSE; |
---|
| 806 | |
---|
| 807 | if (bdd_get_package_name() != CUDD) { |
---|
| 808 | (void) fprintf(vis_stderr, |
---|
| 809 | "** spfd error: The spfd package can be used " |
---|
| 810 | "only with CUDD package\n"); |
---|
| 811 | (void) fprintf(vis_stderr, |
---|
| 812 | "** spfd error: Please link with CUDD package\n"); |
---|
| 813 | return 0; |
---|
| 814 | } |
---|
| 815 | |
---|
| 816 | util_getopt_reset(); |
---|
| 817 | while((c = util_getopt(argc, argv, "D:hn:rt:v:w:")) != EOF) { |
---|
| 818 | switch(c) { |
---|
| 819 | case 'D': |
---|
| 820 | regionDepth = atoi(util_optarg); |
---|
| 821 | break; |
---|
| 822 | case 'h': |
---|
| 823 | goto usage; |
---|
| 824 | case 'n': |
---|
| 825 | netOutFile = util_strsav(util_optarg); |
---|
| 826 | break; |
---|
| 827 | case 'r': |
---|
| 828 | spfdReprogNoWire = FALSE; |
---|
| 829 | break; |
---|
| 830 | case 't': |
---|
| 831 | timeOutPeriod = atoi(util_optarg); |
---|
| 832 | break; |
---|
| 833 | case 'v': |
---|
| 834 | spfdVerbose = atoi(util_optarg); |
---|
| 835 | break; |
---|
| 836 | case 'w': |
---|
| 837 | writeFile = util_strsav(util_optarg); |
---|
| 838 | if ((fp = Cmd_FileOpen(writeFile,"w",NIL(char *),1)) == NIL(FILE)) { |
---|
| 839 | (void) fprintf(vis_stderr, |
---|
| 840 | "** spfd error: Could not open %s for writing.\n", |
---|
| 841 | writeFile); |
---|
| 842 | goto endgame; |
---|
| 843 | } else { |
---|
| 844 | fclose(fp); |
---|
| 845 | } |
---|
| 846 | break; |
---|
| 847 | default: |
---|
| 848 | goto usage; |
---|
| 849 | } |
---|
| 850 | } |
---|
| 851 | |
---|
| 852 | /* netFile, archFile, and placeFile are essential. The user can |
---|
| 853 | specify /dev/null for routeFile if they don't want to store the |
---|
| 854 | routing information */ |
---|
| 855 | if (argc < 5 || argc < util_optind+4) |
---|
| 856 | goto usage; |
---|
| 857 | |
---|
| 858 | /* Get the net, architecture, place and route file names */ |
---|
| 859 | netFile = argv[util_optind]; |
---|
| 860 | archFile = argv[util_optind+1]; |
---|
| 861 | placeFile = argv[util_optind+2]; |
---|
| 862 | routeFile = argv[util_optind+3]; |
---|
| 863 | |
---|
| 864 | if(Hrc_ManagerReadCurrentNode(*hmgr) == NIL(Hrc_Node_t)) { |
---|
| 865 | (void) fprintf(vis_stderr,"** spfd error: The hierarchy manager is empty. " |
---|
| 866 | "Read in design.\n"); |
---|
| 867 | goto endgame; |
---|
| 868 | } |
---|
| 869 | |
---|
| 870 | network = (Ntk_Network_t *) |
---|
| 871 | Hrc_NodeReadApplInfo(Hrc_ManagerReadCurrentNode(*hmgr), |
---|
| 872 | NTK_HRC_NODE_APPL_KEY); |
---|
| 873 | |
---|
| 874 | if(network == NIL(Ntk_Network_t)) { |
---|
| 875 | (void) fprintf(vis_stderr,"** spfd error: There is no network. "); |
---|
| 876 | (void) fprintf(vis_stderr,"Use flatten_hierarchy.\n"); |
---|
| 877 | goto endgame; |
---|
| 878 | } |
---|
| 879 | |
---|
| 880 | /* Check if the current network has signals with multiple values. */ |
---|
| 881 | if (TestIsNetworkMultipleValued(network)) { |
---|
| 882 | (void) fprintf(vis_stderr,"** spfd error: Circuit has multiple " |
---|
| 883 | "valued variables.\n"); |
---|
| 884 | (void) fprintf(vis_stderr,"** spfd error: The algorithm applies " |
---|
| 885 | "to Boolean variables only.\n"); |
---|
| 886 | goto endgame; |
---|
| 887 | } |
---|
| 888 | |
---|
| 889 | if(Ntk_NetworkReadNumPrimaryInputs(network) != |
---|
| 890 | Ntk_NetworkReadNumInputs(network)) { |
---|
| 891 | (void) fprintf(vis_stderr,"** spfd error: Pseudo inputs present " |
---|
| 892 | "in the network.\n"); |
---|
| 893 | (void) fprintf(vis_stderr,"** spfd error: The algorithm does not apply.\n"); |
---|
| 894 | goto endgame; |
---|
| 895 | } |
---|
| 896 | |
---|
| 897 | /* Access a 'total' partition */ |
---|
| 898 | simPart = (graph_t *) Ntk_NetworkReadApplInfo(network, |
---|
| 899 | PART_NETWORK_APPL_KEY); |
---|
| 900 | if (simPart == NIL(graph_t) || |
---|
| 901 | (Part_PartitionReadMethod(simPart) != Part_Total_c)) { |
---|
| 902 | simPart = Part_NetworkCreatePartition(network, |
---|
| 903 | NIL(Hrc_Node_t), |
---|
| 904 | "dummy", (lsList) 0, |
---|
| 905 | (lsList) 0, NIL(mdd_t), |
---|
| 906 | Part_Total_c, |
---|
| 907 | (lsList) 0, |
---|
| 908 | FALSE, FALSE, TRUE); |
---|
| 909 | if (simPart == NIL(graph_t)) { |
---|
| 910 | (void) fprintf(vis_stderr,"** spfd error: Could not create partition.\n"); |
---|
| 911 | goto endgame; |
---|
| 912 | } |
---|
| 913 | Ntk_NetworkAddApplInfo(network,PART_NETWORK_APPL_KEY, |
---|
| 914 | (Ntk_ApplInfoFreeFn)Part_PartitionFreeCallback, |
---|
| 915 | (void *)simPart); |
---|
| 916 | spfdCreatedPart = 1; /* Using new partition */ |
---|
| 917 | (void) fprintf(vis_stdout, |
---|
| 918 | "** spfd info: A new partition created.\n"); |
---|
| 919 | } |
---|
| 920 | |
---|
| 921 | /* Start the timer.*/ |
---|
| 922 | if (timeOutPeriod > 0){ |
---|
| 923 | (void) signal(SIGALRM, (void(*)(int))TimeOutHandle); |
---|
| 924 | (void) alarm(timeOutPeriod); |
---|
| 925 | if (setjmp(timeOutEnv) > 0) { |
---|
| 926 | (void) fprintf(vis_stderr, "** spfd warning: Timeout occurred after "); |
---|
| 927 | (void) fprintf(vis_stderr, "%ld seconds.\n", timeOutPeriod); |
---|
| 928 | alarm(0); |
---|
| 929 | goto endgame; |
---|
| 930 | } |
---|
| 931 | } |
---|
| 932 | |
---|
| 933 | initialTime = util_cpu_time(); |
---|
| 934 | |
---|
| 935 | /* Call the optimization routine. */ |
---|
| 936 | status = SpfdSimultaneousPlacementAndLogicOpt(network,netFile,archFile, |
---|
| 937 | placeFile,routeFile,netOutFile, |
---|
| 938 | regionDepth); |
---|
| 939 | |
---|
| 940 | finalTime = util_cpu_time(); |
---|
| 941 | if(status) { |
---|
| 942 | (void) fprintf(vis_stdout, "%-20s%10ld\n", "** spfd info: analysis time =", |
---|
| 943 | (finalTime-initialTime)/1000); |
---|
| 944 | } |
---|
| 945 | else { |
---|
| 946 | (void) fprintf(vis_stdout, "** spfd error: Optimization failed.\n"); |
---|
| 947 | } |
---|
| 948 | |
---|
| 949 | if (writeFile) { |
---|
| 950 | SpfdNetworkWriteBlifFile(network,writeFile); |
---|
| 951 | FREE(writeFile); |
---|
| 952 | } |
---|
| 953 | |
---|
| 954 | if (netOutFile) { |
---|
| 955 | FREE(netOutFile); |
---|
| 956 | } |
---|
| 957 | |
---|
| 958 | if (spfdCreatedPart) |
---|
| 959 | Ntk_NetworkFreeApplInfo(network,PART_NETWORK_APPL_KEY); |
---|
| 960 | |
---|
| 961 | alarm(0); |
---|
| 962 | return 0; /* normal exit */ |
---|
| 963 | |
---|
| 964 | endgame: |
---|
| 965 | /* Clean up */ |
---|
| 966 | if (writeFile) |
---|
| 967 | FREE(writeFile); |
---|
| 968 | |
---|
| 969 | if (netOutFile) { |
---|
| 970 | FREE(netOutFile); |
---|
| 971 | } |
---|
| 972 | |
---|
| 973 | if (spfdCreatedPart) |
---|
| 974 | Ntk_NetworkFreeApplInfo(network,PART_NETWORK_APPL_KEY); |
---|
| 975 | |
---|
| 976 | return 1; /* Error exit */ |
---|
| 977 | |
---|
| 978 | usage: |
---|
| 979 | |
---|
| 980 | (void) fprintf(vis_stderr, "\nusage: Also see \'help spfd_pdlo\' for more details.\n\n"); |
---|
| 981 | (void) fprintf(vis_stderr, "spfd_pdlo [options] net_file arch_file place_file route_file\n\n"); |
---|
| 982 | (void) fprintf(vis_stderr, " -D <depth>\t\tConsider region upto <depth>.\n\n"); |
---|
| 983 | (void) fprintf(vis_stderr, " -h \t\tCommand usage.\n\n"); |
---|
| 984 | (void) fprintf(vis_stderr, " -n <filename>\tFile to output optimized\n"); |
---|
| 985 | (void) fprintf(vis_stderr, " \t\tcircuit in .net format.\n\n"); |
---|
| 986 | (void) fprintf(vis_stderr, " -r \t\tDo not reprogram internal nodes if there are no\n"); |
---|
| 987 | (void) fprintf(vis_stderr, " \t\tstructural changes in the network.\n\n"); |
---|
| 988 | (void) fprintf(vis_stderr, " -t <N> \t\tTime (s) limit for the command.\n\n"); |
---|
| 989 | (void) fprintf(vis_stderr, " -v <N> \t\tVerbosity level.\n\n"); |
---|
| 990 | (void) fprintf(vis_stderr, " -w <filename>\tFile to output final optimized circuit.\n\n"); |
---|
| 991 | (void) fprintf(vis_stderr, "set options: \n"); |
---|
| 992 | (void) fprintf(vis_stderr, "\tspfd_pdlo_logic_move_freq \"r1 m1 r2 m2 ...\"\n"); |
---|
| 993 | (void) fprintf(vis_stderr, "\t\tPerform m1 logic moves per temperature whenever the rate\n"); |
---|
| 994 | (void) fprintf(vis_stderr, "\t\tof acceptance during simulated annealing is greater than\n"); |
---|
| 995 | (void) fprintf(vis_stderr, "\t\tor equal to r1, and so on. r1 > r2 > r3 ... \n"); |
---|
| 996 | (void) fprintf(vis_stderr, "\t\tand 0 <= ri <= 1.0.\n\n"); |
---|
| 997 | (void) fprintf(vis_stderr, "\tspfd_repl_rem <yes|no>\n"); |
---|
| 998 | (void) fprintf(vis_stderr, "\t\tPerform both wire replacement and removal?\n\n"); |
---|
| 999 | (void) fprintf(vis_stderr, "\tspfd_pdlo_timing\n"); |
---|
| 1000 | (void) fprintf(vis_stderr, "\t\tUse timing driven method.\n"); |
---|
| 1001 | (void) fprintf(vis_stderr, "\t\tIf not set, Bounding box method is used.\n\n"); |
---|
| 1002 | (void) fprintf(vis_stderr, "\tspfd_pdlo_timing_nodeorwire\n"); |
---|
| 1003 | (void) fprintf(vis_stderr, "\t\tProcess the fanouts of the most tcritical node. If not set,\n"); |
---|
| 1004 | (void) fprintf(vis_stderr, "\t\tprocess only the wires on the critical path.\n\n"); |
---|
| 1005 | (void) fprintf(vis_stderr, "\tspfd_pdlo_out_crit_nets_first\n"); |
---|
| 1006 | (void) fprintf(vis_stderr, "\t\tOutput the circuit in VPR\'s .net format with\n"); |
---|
| 1007 | (void) fprintf(vis_stderr, "\t\tnets appearing in the increasing order of their slack.\n"); |
---|
| 1008 | (void) fprintf(vis_stderr, "\t\tIf not set, the initial net order specified in the original\n"); |
---|
| 1009 | (void) fprintf(vis_stderr, "\t\tcircuit\'s .net file is used. The file specified in -n option\n"); |
---|
| 1010 | (void) fprintf(vis_stderr, "\t\tis used. This option is valid only if spfd_pdlo_timing is set.\n\n"); |
---|
| 1011 | (void) fprintf(vis_stderr, "\tspfd_pdlo_remap_clb_array\n"); |
---|
| 1012 | (void) fprintf(vis_stderr, "\t\tReduce the size of FPGA if necessary during\n"); |
---|
| 1013 | (void) fprintf(vis_stderr, "\t\tlogic optimization.\n\n"); |
---|
| 1014 | (void) fprintf(vis_stderr, "set options for VPR: Please see VPR's manual for more information.\n"); |
---|
| 1015 | (void) fprintf(vis_stderr, " vpr_nodisp\n"); |
---|
| 1016 | (void) fprintf(vis_stderr, " vpr_fix_pins\n"); |
---|
| 1017 | (void) fprintf(vis_stderr, " vpr_nx\n"); |
---|
| 1018 | (void) fprintf(vis_stderr, " vpr_ny\n"); |
---|
| 1019 | (void) fprintf(vis_stderr, " vpr_fast\n"); |
---|
| 1020 | (void) fprintf(vis_stderr, " vpr_init_t\n"); |
---|
| 1021 | (void) fprintf(vis_stderr, " vpr_alpha_t \n"); |
---|
| 1022 | (void) fprintf(vis_stderr, " vpr_exit_t\n"); |
---|
| 1023 | (void) fprintf(vis_stderr, " vpr_inner_num\n"); |
---|
| 1024 | (void) fprintf(vis_stderr, " vpr_seed\n"); |
---|
| 1025 | (void) fprintf(vis_stderr, " vpr_place_cost_exp\n"); |
---|
| 1026 | (void) fprintf(vis_stderr, " vpr_place_chan_width\n"); |
---|
| 1027 | return 1; /* error exit */ |
---|
| 1028 | #endif /* ifdef USE_VPR */ |
---|
| 1029 | |
---|
| 1030 | } /* End of CommandSpfdPlaceOptimize */ |
---|
| 1031 | |
---|
| 1032 | |
---|
| 1033 | /**Function******************************************************************** |
---|
| 1034 | |
---|
| 1035 | Synopsis [Handle function for timeout.] |
---|
| 1036 | |
---|
| 1037 | Description [This function is called when the time out occurs.] |
---|
| 1038 | |
---|
| 1039 | SideEffects [] |
---|
| 1040 | |
---|
| 1041 | ******************************************************************************/ |
---|
| 1042 | static void |
---|
| 1043 | TimeOutHandle(void) |
---|
| 1044 | { |
---|
| 1045 | longjmp(timeOutEnv, 1); |
---|
| 1046 | } |
---|
| 1047 | |
---|
| 1048 | /**Function******************************************************************** |
---|
| 1049 | |
---|
| 1050 | Synopsis [Checks whether the network has multiple valued signals.] |
---|
| 1051 | |
---|
| 1052 | Description [Checks whether the network has multiple valued |
---|
| 1053 | signals. Returns 1 if true, else 0.] |
---|
| 1054 | |
---|
| 1055 | SideEffects [None] |
---|
| 1056 | |
---|
| 1057 | SeeAlso [] |
---|
| 1058 | |
---|
| 1059 | ******************************************************************************/ |
---|
| 1060 | static int |
---|
| 1061 | TestIsNetworkMultipleValued(Ntk_Network_t *network) |
---|
| 1062 | { |
---|
| 1063 | Ntk_Node_t *node; |
---|
| 1064 | lsGen gen; |
---|
| 1065 | Var_Variable_t *var; |
---|
| 1066 | int numValues; |
---|
| 1067 | |
---|
| 1068 | Ntk_NetworkForEachNode(network,gen,node) { |
---|
| 1069 | var = Ntk_NodeReadVariable(node); |
---|
| 1070 | numValues = Var_VariableReadNumValues(var); |
---|
| 1071 | if (numValues > 2) |
---|
| 1072 | return 1; |
---|
| 1073 | } |
---|
| 1074 | return 0; |
---|
| 1075 | } |
---|
| 1076 | |
---|
| 1077 | #ifndef USE_VPR |
---|
| 1078 | /**Function******************************************************************** |
---|
| 1079 | |
---|
| 1080 | Synopsis [Dummy function] |
---|
| 1081 | |
---|
| 1082 | SideEffects [None] |
---|
| 1083 | |
---|
| 1084 | ******************************************************************************/ |
---|
| 1085 | static int |
---|
| 1086 | SpfdSimultaneousPlacementAndLogicOpt( |
---|
| 1087 | Ntk_Network_t *network, |
---|
| 1088 | char *netFile, |
---|
| 1089 | char *archFile, |
---|
| 1090 | char *placeFile, |
---|
| 1091 | char *routeFile, |
---|
| 1092 | char *netOutFile, |
---|
| 1093 | int regionDepth) |
---|
| 1094 | { |
---|
| 1095 | return 0; |
---|
| 1096 | } |
---|
| 1097 | #endif |
---|