source: vis_dev/vis-2.3/src/spfd/spfdCmd.c @ 45

Last change on this file since 45 was 14, checked in by cecile, 13 years ago

vis2.3

File size: 40.3 KB
Line 
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
23static 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
43static jmp_buf timeOutEnv; /* time out */
44int spfdCreatedPart; /* Whether network BDDs were created in the package */
45int spfdVerbose; /* verbosity */
46float spfdAlpha; /* spfdAlpha * load + (1-spfdAlpha) * topDepth, is used to order
47                fanin nodes during SPFD computation */
48boolean spfdPerfSim; /* Perform simulation */
49boolean spfdNtkChanged; /* TRUE if network changes structurally or functionally */
50boolean spfdReprogNoWire; /* If TRUE, no functional changes are performed
51                         unless required by structural changes */
52int spfdWiresAdded, spfdNumWiresRem; /* Number of wires added and removed */
53int spfdSortNodes; /* Method to sort nodes */
54int spfdMethod; /* Optimization method */
55
56/*---------------------------------------------------------------------------*/
57/* Macro declarations                                                        */
58/*---------------------------------------------------------------------------*/
59
60
61/**AutomaticStart*************************************************************/
62
63/*---------------------------------------------------------------------------*/
64/* Static function prototypes                                                */
65/*---------------------------------------------------------------------------*/
66
67static int CommandSpfdNetworkOptimize(Hrc_Manager_t **hmgr, int argc, char **argv);
68static int CommandSpfdPlaceOptimize(Hrc_Manager_t **hmgr, int argc, char **argv);
69static void TimeOutHandle(void);
70static int TestIsNetworkMultipleValued(Ntk_Network_t *network);
71static 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******************************************************************************/
89void
90Spfd_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******************************************************************************/
106void
107Spfd_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 &lt;alpha&gt;
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 &lt;depth&gt;
183   <dd> A cluster is computed which includes nodes within the specified
184   'depth'. The default value is 1.<p>
185
186   <dt> -f &lt;file&gt;
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 &lt;freq&gt;
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 &lt;n&gt;
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 &lt;percent&gt;
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 &lt;n&gt;
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 &lt;sec&gt;
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 &lt;n&gt;
248   <dd> Verbosity level. Default value is 0.<p>
249
250   <dt> -w &lt;file&gt;
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******************************************************************************/
267static int
268CommandSpfdNetworkOptimize(
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
522endgame:
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
535usage:
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 &lt;depth&gt;\] \[-h\] \[-n &lt;file&gt;\]
592   \[-r\] \[-t &lt;sec&gt;\] \[-v &lt;n&gt;\] \[-w &lt;file&gt;\]
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 &lt;depth&gt;
646   <dd> A cluster is computed which includes nodes within the specified
647   'depth'. The default value is 1.<p>
648
649   <dt> -n &lt;file&gt;
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 &lt;sec&gt;
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 &lt;n&gt;
665   <dd> Verbosity level.<p>
666
667   <dt> -w &lt;file&gt;
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******************************************************************************/
761static int
762CommandSpfdPlaceOptimize(
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
964endgame:
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
978usage:
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******************************************************************************/
1042static void
1043TimeOutHandle(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******************************************************************************/
1060static int
1061TestIsNetworkMultipleValued(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******************************************************************************/
1085static int 
1086SpfdSimultaneousPlacementAndLogicOpt(
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
Note: See TracBrowser for help on using the repository browser.