1 | /**CFile*********************************************************************** |
---|
2 | |
---|
3 | FileName [ordMain.c] |
---|
4 | |
---|
5 | PackageName [ord] |
---|
6 | |
---|
7 | Synopsis [Routines for static ordering of MDD variables.] |
---|
8 | |
---|
9 | Author [Adnan Aziz, Tom Shiple, Serdar Tasiran] |
---|
10 | |
---|
11 | Copyright [Copyright (c) 1994-1996 The Regents of the Univ. of California. |
---|
12 | All rights reserved. |
---|
13 | |
---|
14 | Permission is hereby granted, without written agreement and without license |
---|
15 | or royalty fees, to use, copy, modify, and distribute this software and its |
---|
16 | documentation for any purpose, provided that the above copyright notice and |
---|
17 | the following two paragraphs appear in all copies of this software. |
---|
18 | |
---|
19 | IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR |
---|
20 | DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT |
---|
21 | OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF |
---|
22 | CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
23 | |
---|
24 | THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, |
---|
25 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
---|
26 | FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN |
---|
27 | "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE |
---|
28 | MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.] |
---|
29 | |
---|
30 | ******************************************************************************/ |
---|
31 | |
---|
32 | #include "ordInt.h" |
---|
33 | |
---|
34 | static char rcsid[] UNUSED = "$Id: ordMain.c,v 1.17 2005/04/16 06:15:25 fabio Exp $"; |
---|
35 | |
---|
36 | /*---------------------------------------------------------------------------*/ |
---|
37 | /* Constant declarations */ |
---|
38 | /*---------------------------------------------------------------------------*/ |
---|
39 | |
---|
40 | /*---------------------------------------------------------------------------*/ |
---|
41 | /* Structure declarations */ |
---|
42 | /*---------------------------------------------------------------------------*/ |
---|
43 | |
---|
44 | /**AutomaticStart*************************************************************/ |
---|
45 | |
---|
46 | /*---------------------------------------------------------------------------*/ |
---|
47 | /* Static function prototypes */ |
---|
48 | /*---------------------------------------------------------------------------*/ |
---|
49 | |
---|
50 | static int NodesCompareDepth(Ntk_Node_t *node1, Ntk_Node_t *node2); |
---|
51 | static long NodeComputeDepth(Ntk_Node_t * node); |
---|
52 | static void NetworkAddDanglingNodesToOrderList(Ntk_Network_t * network, lsList nodeOrderList, st_table *nodeToHandle); |
---|
53 | static void NetworkAddNSVarsToOrderList(Ntk_Network_t * network, lsList nodeOrderList, st_table *nodeToHandle, boolean nsAfterSupport); |
---|
54 | static lsList LatchNSListConvertToLatchDataInputList(lsList latchNSList); |
---|
55 | static void NodeSetDepth(Ntk_Node_t * node, long depth); |
---|
56 | static void MddGroupVariables(mdd_manager *mddMgr, int initMddId, int blockSize); |
---|
57 | |
---|
58 | /**AutomaticEnd***************************************************************/ |
---|
59 | |
---|
60 | |
---|
61 | /*---------------------------------------------------------------------------*/ |
---|
62 | /* Definition of exported functions */ |
---|
63 | /*---------------------------------------------------------------------------*/ |
---|
64 | |
---|
65 | /**Function******************************************************************** |
---|
66 | |
---|
67 | Synopsis [Orders the MDD variables of a network.] |
---|
68 | |
---|
69 | Description [Orders the MDD variables of a network. The ordering is based |
---|
70 | solely on the topology of the network; the binary variables that make up the |
---|
71 | MDD variables are not interleaved. OutputOrderType can be either Ord_All_c |
---|
72 | or Ord_InputAndLatch_c. If it is Ord_All_c, then every node (and latch NS) |
---|
73 | in the network is assigned an MDD id. If it is Ord_InputAndLatch_c, then |
---|
74 | every primary input, pseudo input, latch, and latch NS is assigned an MDD |
---|
75 | id.<p> |
---|
76 | |
---|
77 | SuppliedOrderType can be any value of Ord_OrderType. If it is Ord_All_c or |
---|
78 | Ord_InputAndLatch_c, then suppliedNodeList must give an ordering of the |
---|
79 | network nodes (included in the set specified by suppliedOrderType). |
---|
80 | Otherwise, Ord_NetworkOrderNodes is called, with the same arguments as this |
---|
81 | function, to compute an ordering of the network nodes. In any case, the |
---|
82 | ordering of nodes is projected onto the set specified by generatedOrderType, |
---|
83 | and MDD ids are assigned (in order) to the nodes in the projection. The |
---|
84 | starting MDD id is the total number of variables currently in the MDD |
---|
85 | manager of the network. An MDD manager is created for the network if one |
---|
86 | doesn't already exist.<p> |
---|
87 | |
---|
88 | No checks are made to insure that suppliedNodeList contains what is implied |
---|
89 | by the value of suppliedOrderType. The MDD ids of nodes not specified by |
---|
90 | generatedOrderType are unaffected.<p> |
---|
91 | |
---|
92 | If nsAfterSupport is TRUE, then for a given latch, its next state variable |
---|
93 | is ordered just after the variables in the support of the latch's |
---|
94 | corresponding dataInput function. <p> |
---|
95 | |
---|
96 | If nsAfterSupport is FALSE, then for a given latch, its NS variable is |
---|
97 | ordered just after the corresponding present state variable. In this case, |
---|
98 | the ps variable and the ns variable are grouped together in the variable |
---|
99 | ordering, so that when reordering is performed they remain adjacent in the |
---|
100 | new variable ordering. Similarly, when an ordering is read from a file, NS |
---|
101 | variables immediately following corresponding PS variables are grouped |
---|
102 | together.<p>] |
---|
103 | |
---|
104 | SideEffects [Writes over the MDD id field of nodes.] |
---|
105 | |
---|
106 | SeeAlso [Ord_NetworkOrderNodes] |
---|
107 | |
---|
108 | ******************************************************************************/ |
---|
109 | void |
---|
110 | Ord_NetworkOrderVariables( |
---|
111 | Ntk_Network_t *network, |
---|
112 | Ord_RootMethod rootOrderMethod, |
---|
113 | Ord_NodeMethod nodeOrderMethod, |
---|
114 | boolean nsAfterSupport, |
---|
115 | Ord_OrderType generatedOrderType /* Ord_All_c or Ord_InputAndLatch_c */, |
---|
116 | Ord_OrderType suppliedOrderType /* no restrictions */, |
---|
117 | lsList suppliedNodeList /* list of nodes Ntk_Node_t* from ordering file */, |
---|
118 | int verbose) |
---|
119 | { |
---|
120 | lsList totalOrderList; /* list of nodes (Ntk_Node_t *) */ |
---|
121 | long initialTime = util_cpu_time(); |
---|
122 | |
---|
123 | /* |
---|
124 | * The condition where suppliedOrderType==InputAndLatch and |
---|
125 | * generatedOrderType==All is not currently allowed because we're not sure |
---|
126 | * if it's useful. |
---|
127 | */ |
---|
128 | assert(!((suppliedOrderType == Ord_InputAndLatch_c) |
---|
129 | && (generatedOrderType == Ord_All_c))); |
---|
130 | |
---|
131 | /* |
---|
132 | * Either get a total ordering of the network nodes from suppliedNodeList, |
---|
133 | * or compute it working from the network. |
---|
134 | */ |
---|
135 | if ((suppliedOrderType == Ord_All_c) |
---|
136 | || (suppliedOrderType == Ord_InputAndLatch_c)) { |
---|
137 | totalOrderList = lsCopy(suppliedNodeList, |
---|
138 | (lsGeneric (*) (lsGeneric)) NULL); |
---|
139 | } |
---|
140 | else { |
---|
141 | totalOrderList = Ord_NetworkOrderNodes(network, rootOrderMethod, |
---|
142 | nodeOrderMethod, nsAfterSupport, |
---|
143 | generatedOrderType, |
---|
144 | suppliedOrderType, |
---|
145 | suppliedNodeList, |
---|
146 | verbose); |
---|
147 | } |
---|
148 | |
---|
149 | |
---|
150 | OrdNetworkAssignMddIds(network, generatedOrderType, totalOrderList, nsAfterSupport); |
---|
151 | (void) lsDestroy(totalOrderList, (void (*) (lsGeneric)) NULL); |
---|
152 | |
---|
153 | /* |
---|
154 | * If nsAfterSupport is FALSE, this implies that NS comes right after PS. |
---|
155 | * |
---|
156 | */ |
---|
157 | if ( nsAfterSupport == FALSE ) { |
---|
158 | lsGen tmpGen; |
---|
159 | Ntk_Node_t *tmpLatch; |
---|
160 | |
---|
161 | /* |
---|
162 | * Iterate over each latch, and group the PS variable with the next |
---|
163 | * variable in the ordering, which is guaranteed to be the corresponding NS |
---|
164 | * variable. |
---|
165 | */ |
---|
166 | Ntk_NetworkForEachLatch(network, tmpGen, tmpLatch) { |
---|
167 | mdd_manager *mddMgr = Ntk_NetworkReadMddManager( network ); |
---|
168 | Ntk_Node_t *nsNode = Ntk_NodeReadShadow( tmpLatch ); |
---|
169 | int psMddId = Ntk_NodeReadMddId( tmpLatch ); |
---|
170 | int nsMddId = Ntk_NodeReadMddId( nsNode ); |
---|
171 | |
---|
172 | /* |
---|
173 | * Group size = 2 ( ps and ns ) |
---|
174 | */ |
---|
175 | if (nsMddId == (psMddId+1)) { |
---|
176 | MddGroupVariables(mddMgr, psMddId, 2); |
---|
177 | } |
---|
178 | /* Adnan's fix: See his mail to vis@ic on Oct 24, 1997 */ |
---|
179 | if (nsMddId == (psMddId-1)) { |
---|
180 | MddGroupVariables(mddMgr, nsMddId, 2); |
---|
181 | } |
---|
182 | } |
---|
183 | } |
---|
184 | |
---|
185 | if (verbose > 0) { |
---|
186 | long finalTime = util_cpu_time(); |
---|
187 | (void) fprintf(vis_stdout, "\nTotal ordering time = %2.1f\n", |
---|
188 | (finalTime-initialTime)/1000.0); |
---|
189 | } |
---|
190 | } |
---|
191 | |
---|
192 | |
---|
193 | /**Function******************************************************************** |
---|
194 | |
---|
195 | Synopsis [Orders the nodes of a network.] |
---|
196 | |
---|
197 | Description [Orders the nodes of a network. The ordering is based solely on |
---|
198 | the topology of the network, and is intended to be suitable for deriving an |
---|
199 | MDD variable ordering by extracting those nodes for which MDD variables are |
---|
200 | needed. GeneratedOrderType can be either Ord_All_c or |
---|
201 | Ord_InputAndLatch_c. If it is Ord_All_c, then every node (and latch NS) in |
---|
202 | the network is ordered. If it is Ord_InputAndLatch_c, then every primary |
---|
203 | input, pseudo input, latch, and latch NS is ordered. <p> |
---|
204 | |
---|
205 | SuppliedOrderType can be any of the following values: Ord_NextStateNode_c, |
---|
206 | Ord_Partial_c, or Ord_Unassigned_c. If it is Ord_Unassigned_c, then |
---|
207 | suppliedNodeList is ignored, and there is no effect. If it is *not* |
---|
208 | Ord_Unassigned_c, then suppliedNodeList must be a non-empty list of |
---|
209 | (pointers to) nodes. SuppliedNodeList can be used to specify the relative |
---|
210 | order of some or the nodes.<p> |
---|
211 | |
---|
212 | If suppliedOrderType is Ord_NextStateNode_c, then suppliedNodeList should |
---|
213 | contain a complete list of next state nodes; the transitive fanins of the |
---|
214 | latches are visited according to the order of the next state nodes in |
---|
215 | suppliedNodeList. If suppliedOrderType is Ord_Partial_c, then |
---|
216 | suppliedNodeList may contain an arbitrary subset of network nodes; in this |
---|
217 | case, an ordering is found disregarding suppliedNodeList, and then this |
---|
218 | ordering is merged into the suppliedNodeList. No checks are made to insure |
---|
219 | that suppliedNodeList contains what is implied by the value of |
---|
220 | suppliedOrderType.<p> |
---|
221 | |
---|
222 | If nsAfterSupport is TRUE, then for a given latch, its next state variable |
---|
223 | is ordered just after the latch's corresponding dataInput node. If |
---|
224 | nsAfterSupport is FALSE, then for a given latch, its next state variable is |
---|
225 | ordered just after the latch (i.e. its present state variable). (If the |
---|
226 | latch itself is not present yet in the nodeOrderList, then first adds latch |
---|
227 | to the end of the ordering.)] |
---|
228 | |
---|
229 | SideEffects [] |
---|
230 | |
---|
231 | SeeAlso [Ord_NetworkOrderVariables] |
---|
232 | |
---|
233 | ******************************************************************************/ |
---|
234 | lsList |
---|
235 | Ord_NetworkOrderNodes( |
---|
236 | Ntk_Network_t *network, |
---|
237 | Ord_RootMethod rootOrderMethod, |
---|
238 | Ord_NodeMethod nodeOrderMethod, |
---|
239 | boolean nsAfterSupport, |
---|
240 | Ord_OrderType generatedOrderType /* Ord_All_c or Ord_InputAndLatch_c */, |
---|
241 | Ord_OrderType suppliedOrderType /* Ord_NextStateNode_c, Ord_Partial_c, or |
---|
242 | Ord_Unassigned_c */, |
---|
243 | lsList suppliedNodeList /* list of nodes Ntk_Node_t* from ordering file */, |
---|
244 | int verbose) |
---|
245 | { |
---|
246 | lsList partialRootOrder; /* list of nodes (Ntk_Node_t *) */ |
---|
247 | lsList roots; /* list of nodes (Ntk_Node_t *) */ |
---|
248 | lsList nodeOrderList; /* list of nodes (Ntk_Node_t *) */ |
---|
249 | st_table *nodeToHandle; /* Ntk_Node_t* to lsHandle */ |
---|
250 | |
---|
251 | /* |
---|
252 | * Check the input arguments. |
---|
253 | */ |
---|
254 | assert( (generatedOrderType == Ord_All_c) |
---|
255 | || (generatedOrderType == Ord_InputAndLatch_c)); |
---|
256 | |
---|
257 | assert( (suppliedOrderType == Ord_NextStateNode_c) |
---|
258 | || (suppliedOrderType == Ord_Partial_c) |
---|
259 | || (suppliedOrderType == Ord_Unassigned_c)); |
---|
260 | |
---|
261 | |
---|
262 | /* |
---|
263 | * Compute an ordering on the roots. The nodes of the network are explored |
---|
264 | * in DFS order from the roots, in the root order computed. If |
---|
265 | * suppliedOrderType is Ord_NextStateNode_c, then suppliedNodeList contains |
---|
266 | * the next state nodes; this list serves as a seed to compute the root |
---|
267 | * ordering. |
---|
268 | */ |
---|
269 | partialRootOrder = (suppliedOrderType == Ord_NextStateNode_c) |
---|
270 | ? LatchNSListConvertToLatchDataInputList(suppliedNodeList) |
---|
271 | : (lsList) NULL; |
---|
272 | roots = Ord_NetworkOrderRoots(network, rootOrderMethod, |
---|
273 | partialRootOrder, verbose); |
---|
274 | if (suppliedOrderType == Ord_NextStateNode_c) { |
---|
275 | (void) lsDestroy(partialRootOrder, (void (*) (lsGeneric)) NULL); |
---|
276 | } |
---|
277 | if (verbose > 0) { |
---|
278 | (void) fprintf(vis_stdout, "\nOrder in which roots are visited:\n"); |
---|
279 | OrdNodeListWrite(vis_stdout, roots); |
---|
280 | } |
---|
281 | |
---|
282 | /* |
---|
283 | * Compute an order on all nodes in the transitive fanin of roots, including |
---|
284 | * the roots themselves. Pass in an empty nodeToHandle table. |
---|
285 | */ |
---|
286 | nodeToHandle = st_init_table(st_ptrcmp, st_ptrhash); |
---|
287 | nodeOrderList = OrdNetworkOrderTFIOfRoots(network, roots, nodeOrderMethod, |
---|
288 | nodeToHandle, verbose); |
---|
289 | (void) lsDestroy(roots, (void (*) (lsGeneric)) NULL); |
---|
290 | |
---|
291 | if (verbose > 0) { |
---|
292 | (void) fprintf(vis_stdout, "\nOrder of network nodes without NS:\n"); |
---|
293 | OrdNodeListWrite(vis_stdout, nodeOrderList); |
---|
294 | } |
---|
295 | |
---|
296 | /* |
---|
297 | * Add in the next state variables (represented by the shadow nodes of |
---|
298 | * latches). |
---|
299 | */ |
---|
300 | NetworkAddNSVarsToOrderList(network, nodeOrderList, nodeToHandle, nsAfterSupport); |
---|
301 | if (verbose > 2) { |
---|
302 | (void) fprintf(vis_stdout, "\nOrder of network nodes with NS:\n"); |
---|
303 | OrdNodeListWrite(vis_stdout, nodeOrderList); |
---|
304 | } |
---|
305 | |
---|
306 | |
---|
307 | /* |
---|
308 | * There may be some nodes that are not in the TFI of any root. Put such |
---|
309 | * nodes at the end of nodeOrderList (in no particular order). |
---|
310 | */ |
---|
311 | NetworkAddDanglingNodesToOrderList(network, nodeOrderList, nodeToHandle); |
---|
312 | st_free_table(nodeToHandle); |
---|
313 | |
---|
314 | /* |
---|
315 | * If the suppliedOrderType is Partial, then merge (left, arbitrarily) the |
---|
316 | * computed node order into the supplied node order and return the result. |
---|
317 | * Otherwise, just return the nodeOrderList computed. |
---|
318 | */ |
---|
319 | if (suppliedOrderType == Ord_Partial_c) { |
---|
320 | lsList suppliedNodeListCopy = lsCopy(suppliedNodeList, |
---|
321 | (lsGeneric (*) (lsGeneric)) NULL); |
---|
322 | |
---|
323 | Ord_ListMergeList(suppliedNodeListCopy, nodeOrderList, Ord_ListMergeLeft_c); |
---|
324 | (void) lsDestroy(nodeOrderList, (void (*) (lsGeneric)) NULL); |
---|
325 | return suppliedNodeListCopy; |
---|
326 | } |
---|
327 | else { |
---|
328 | return nodeOrderList; |
---|
329 | } |
---|
330 | } |
---|
331 | |
---|
332 | |
---|
333 | /**Function******************************************************************** |
---|
334 | |
---|
335 | Synopsis [Assigns an mddId to a node.] |
---|
336 | |
---|
337 | Description [Assigns an mddId to a node. If the node already has a valid |
---|
338 | mddId (i.e. it is not NTK_UNASSIGNED_MDD_ID), then nothing is done. |
---|
339 | Otherwise, the node is assigned an mddId, and this Id is created within the |
---|
340 | MDD manager of the network. (An MDD manager is created for the network if |
---|
341 | the network doesn't already have one.) ] |
---|
342 | |
---|
343 | SideEffects [] |
---|
344 | |
---|
345 | Comment [(Tom): this should be more intelligent, and get the id from the |
---|
346 | total ordering on all the network nodes, and then do insertion into variable |
---|
347 | ordering. Use ntk appl info to store total node order.] |
---|
348 | |
---|
349 | ******************************************************************************/ |
---|
350 | void |
---|
351 | Ord_NetworkAssignMddIdForNode( |
---|
352 | Ntk_Network_t *network, |
---|
353 | Ntk_Node_t *node) |
---|
354 | { |
---|
355 | if (Ntk_NodeReadMddId(node) != NTK_UNASSIGNED_MDD_ID) { |
---|
356 | return; |
---|
357 | } |
---|
358 | else { |
---|
359 | int mddId; |
---|
360 | mdd_manager *mddManager = Ntk_NetworkReadMddManager(network); |
---|
361 | array_t *mvarValues = array_alloc(int, 0); |
---|
362 | array_t *mvarNames = array_alloc(char *, 0); |
---|
363 | |
---|
364 | /* |
---|
365 | * If the network doesn't already have an MDD manager, then create one. In |
---|
366 | * any case, set mddId to be the number of variables currently existing in |
---|
367 | * the manager. |
---|
368 | */ |
---|
369 | if (mddManager == NIL(mdd_manager)) { |
---|
370 | mddManager = Ntk_NetworkInitializeMddManager(network); |
---|
371 | mddId = 0; |
---|
372 | } |
---|
373 | else { |
---|
374 | array_t *mvarArray = mdd_ret_mvar_list(mddManager); |
---|
375 | mddId = array_n(mvarArray); |
---|
376 | } |
---|
377 | |
---|
378 | Ntk_NodeSetMddId(node, mddId); |
---|
379 | |
---|
380 | array_insert_last(int, mvarValues, |
---|
381 | Var_VariableReadNumValues(Ntk_NodeReadVariable(node))); |
---|
382 | array_insert_last(char *, mvarNames, Ntk_NodeReadName(node)); |
---|
383 | |
---|
384 | /* |
---|
385 | * Create the variable in the MDD manager. The last argument being NIL |
---|
386 | * means that the variable will not be interleaved. |
---|
387 | */ |
---|
388 | mdd_create_variables(mddManager, mvarValues, mvarNames, NIL(array_t)); |
---|
389 | |
---|
390 | array_free(mvarValues); |
---|
391 | array_free(mvarNames); |
---|
392 | } |
---|
393 | } |
---|
394 | |
---|
395 | |
---|
396 | /**Function******************************************************************** |
---|
397 | |
---|
398 | Synopsis [Merges left list2 into list1, using the provided table for efficiency.] |
---|
399 | |
---|
400 | Description [Merges left list2 into list1, using the provided table for |
---|
401 | efficiency. dataToHandle1 is a hash table mapping each item in list1 to its |
---|
402 | handle in list1. <p> |
---|
403 | |
---|
404 | This function implements the merge described in Algorithm 1 by Fujii et al., |
---|
405 | "Interleaving Based Variable Ordering Methods for OBDDs", ICCAD 1993, p. 38. |
---|
406 | For each item in list2: if item is already present in list1, do nothing; |
---|
407 | else if item is the head of list2, then insert item at the head of list1; |
---|
408 | else, insert item into list1 immediately following the location in list1 of |
---|
409 | the item's predessor item in list2. This has the effect of locating the |
---|
410 | items in list2 as far to the left as possible in list1, while still |
---|
411 | preserving the partial order for those elements of list2 not initially |
---|
412 | appearing in list1 (a "merge left"). Examples: |
---|
413 | |
---|
414 | <pre> |
---|
415 | list1=abc, list2=dbe --> list1=dabec |
---|
416 | list1=abc, list2=deb --> list1=deabc. |
---|
417 | </pre> |
---|
418 | |
---|
419 | Note that this merging is not commutative. That is, Ord_ListMergeLeftList(l1,l2) |
---|
420 | may give a different ordering than Ord_ListMergeLeftList(l2,l1).] |
---|
421 | |
---|
422 | SideEffects [List1 is modified, and dataToHandle1 is modified to reflect the |
---|
423 | newly inserted items.] |
---|
424 | |
---|
425 | Comment [All references to "handle" in the code are references to |
---|
426 | handles in list1. We never reference or care about handles in list2. ] |
---|
427 | |
---|
428 | SeeAlso [Ord_ListMergeRightListUsingTable] |
---|
429 | |
---|
430 | ******************************************************************************/ |
---|
431 | void |
---|
432 | Ord_ListMergeLeftListUsingTable( |
---|
433 | lsList list1, |
---|
434 | lsList list2, |
---|
435 | st_table *dataToHandle1) |
---|
436 | { |
---|
437 | lsGen gen1; /* generator for list1 */ |
---|
438 | lsGen gen2; /* generator for list2 */ |
---|
439 | lsHandle handle; /* handle of an item in list1 */ |
---|
440 | lsGeneric data; |
---|
441 | lsGeneric prevData; |
---|
442 | |
---|
443 | /* |
---|
444 | * Walk through list2 forwards, keeping track of the previous item just visited. |
---|
445 | */ |
---|
446 | gen2 = lsStart(list2); |
---|
447 | prevData = NULL; |
---|
448 | while (lsNext(gen2, &data, LS_NH) == LS_OK) { |
---|
449 | |
---|
450 | if (!st_is_member(dataToHandle1, (char *) data)) { |
---|
451 | /* |
---|
452 | * Data is not present in list1, so we must insert it at the proper |
---|
453 | * location. |
---|
454 | */ |
---|
455 | if (prevData == NULL) { |
---|
456 | /* |
---|
457 | * Data is the head of list2, so insert it at the head of list1. |
---|
458 | */ |
---|
459 | (void) lsNewBegin(list1, data, &handle); |
---|
460 | } |
---|
461 | else { |
---|
462 | lsGeneric dummyData; |
---|
463 | lsHandle prevHandle; |
---|
464 | |
---|
465 | /* |
---|
466 | * Data is not the head of list1. Hence, insert it just to the right |
---|
467 | * of the location of prevData in list1 (by induction, prevData must |
---|
468 | * currently exist in list1). Do this by getting the handle of |
---|
469 | * prevData in list1, creating a generator initialized to just after |
---|
470 | * prevData, and then inserting data at this point. Note that |
---|
471 | * lsInAfter and lsInBefore are equivalent in this case, since we |
---|
472 | * immediately kill gen1. |
---|
473 | */ |
---|
474 | st_lookup(dataToHandle1, prevData, &prevHandle); |
---|
475 | gen1 = lsGenHandle(prevHandle, &dummyData, LS_AFTER); |
---|
476 | (void) lsInAfter(gen1, data, &handle); |
---|
477 | (void) lsFinish(gen1); |
---|
478 | } |
---|
479 | st_insert(dataToHandle1, data, handle); |
---|
480 | |
---|
481 | } /* else, data already present in list1, so do nothing */ |
---|
482 | |
---|
483 | prevData = data; |
---|
484 | |
---|
485 | } /* end while */ |
---|
486 | (void) lsFinish(gen2); |
---|
487 | } |
---|
488 | |
---|
489 | |
---|
490 | /**Function******************************************************************** |
---|
491 | |
---|
492 | Synopsis [Merges right list2 into list1, using the provided table for efficiency.] |
---|
493 | |
---|
494 | Description [Merges right list2 into list1, using the provided table for |
---|
495 | efficiency. This function is the same as Ord_ListMergeLeftListUsingTable, |
---|
496 | except that a "merge right" is done, rather than a "merge left". For each |
---|
497 | item in list2: if item is already present in list1, do nothing; else if item |
---|
498 | is the tail of list2, then insert item at the tail of list1; else, insert |
---|
499 | item into list1 immediately preceeding the location in list1 of the item's |
---|
500 | successor item in list2. This has the effect of locating the items in list2 |
---|
501 | as far to the right as possible in list1, while still preserving the partial |
---|
502 | order for those elements of list2 not initially appearing in list1 (a "merge |
---|
503 | right"). Examples: |
---|
504 | |
---|
505 | <pre> |
---|
506 | list1=abc, list2=dbe --> list1=adbce |
---|
507 | list1=abc, list2=deb --> list1=adebc. |
---|
508 | </pre> |
---|
509 | |
---|
510 | ] |
---|
511 | |
---|
512 | SideEffects [List1 is modified, and dataToHandle1 is modified to reflect the |
---|
513 | newly inserted items.] |
---|
514 | |
---|
515 | Comment [All references to "handle" in the code are references to |
---|
516 | handles in list1. We never reference or care about handles in list2. ] |
---|
517 | |
---|
518 | SeeAlso [Ord_ListMergeLeftListUsingTable] |
---|
519 | |
---|
520 | ******************************************************************************/ |
---|
521 | void |
---|
522 | Ord_ListMergeRightListUsingTable( |
---|
523 | lsList list1, |
---|
524 | lsList list2, |
---|
525 | st_table *dataToHandle1) |
---|
526 | { |
---|
527 | lsGen gen1; /* generator for list1 */ |
---|
528 | lsGen gen2; /* generator for list2 */ |
---|
529 | lsHandle handle; /* handle of an item in list1 */ |
---|
530 | lsGeneric data; |
---|
531 | lsGeneric succData; |
---|
532 | |
---|
533 | /* |
---|
534 | * Walk through list2 backwards, keeping track of the successor item just visited. |
---|
535 | */ |
---|
536 | gen2 = lsEnd(list2); |
---|
537 | succData = NULL; |
---|
538 | while (lsPrev(gen2, &data, LS_NH) == LS_OK) { |
---|
539 | |
---|
540 | if (!st_is_member(dataToHandle1, (char *) data)) { |
---|
541 | /* |
---|
542 | * Data is not present in list1, so we must insert it at the proper |
---|
543 | * location. |
---|
544 | */ |
---|
545 | if (succData == NULL) { |
---|
546 | /* |
---|
547 | * Data is the tail of list2, so insert it at the tail of list1. |
---|
548 | */ |
---|
549 | (void) lsNewEnd(list1, data, &handle); |
---|
550 | } |
---|
551 | else { |
---|
552 | lsGeneric dummyData; |
---|
553 | lsHandle succHandle; |
---|
554 | |
---|
555 | /* |
---|
556 | * Data is not the tail of list1. Hence, insert it just to the left |
---|
557 | * of the location of succData in list1 (by induction, succData must |
---|
558 | * currently exist in list1). Do this by getting the handle of |
---|
559 | * succData in list1, creating a generator initialized to just before |
---|
560 | * succData, and then inserting data at this point. Note that |
---|
561 | * lsInAfter and lsInBefore are equivalent in this case, since we are |
---|
562 | * immediately kill gen1. |
---|
563 | */ |
---|
564 | st_lookup(dataToHandle1, succData, &succHandle); |
---|
565 | gen1 = lsGenHandle(succHandle, &dummyData, LS_BEFORE); |
---|
566 | (void) lsInAfter(gen1, data, &handle); |
---|
567 | (void) lsFinish(gen1); |
---|
568 | } |
---|
569 | st_insert(dataToHandle1, data, handle); |
---|
570 | |
---|
571 | } /* else, data already present in list1, so do nothing */ |
---|
572 | |
---|
573 | succData = data; |
---|
574 | |
---|
575 | } /* end while */ |
---|
576 | (void) lsFinish(gen2); |
---|
577 | } |
---|
578 | |
---|
579 | |
---|
580 | /**Function******************************************************************** |
---|
581 | |
---|
582 | Synopsis [Merges list2 into list1, using the provided table for efficiency.] |
---|
583 | |
---|
584 | Description [Merges list2 into list1, using the provided table for |
---|
585 | efficiency. Calls Ord_ListMergeLeftListUsingTable or |
---|
586 | Ord_ListMergeRightListUsingTable depending on the value of method.] |
---|
587 | |
---|
588 | SideEffects [list1 is modified] |
---|
589 | |
---|
590 | SeeAlso [Ord_ListMergeLeftListUsingTable Ord_ListMergeRightListUsingTable] |
---|
591 | |
---|
592 | ******************************************************************************/ |
---|
593 | void |
---|
594 | Ord_ListMergeListUsingTable( |
---|
595 | lsList list1, |
---|
596 | lsList list2, |
---|
597 | st_table *dataToHandle1, |
---|
598 | Ord_ListMergeMethod method) |
---|
599 | { |
---|
600 | if (method == Ord_ListMergeLeft_c) { |
---|
601 | Ord_ListMergeLeftListUsingTable(list1, list2, dataToHandle1); |
---|
602 | } |
---|
603 | else if (method == Ord_ListMergeRight_c) { |
---|
604 | Ord_ListMergeRightListUsingTable(list1, list2, dataToHandle1); |
---|
605 | } |
---|
606 | else { |
---|
607 | fail("unrecognized method"); |
---|
608 | } |
---|
609 | } |
---|
610 | |
---|
611 | |
---|
612 | /**Function******************************************************************** |
---|
613 | |
---|
614 | Synopsis [Merges list2 into list1.] |
---|
615 | |
---|
616 | Description [Merges list2 into list1. Creates a hash table mapping the items |
---|
617 | of list1 to their handles in list1, and then calls Ord_ListMergeListUsingTable.] |
---|
618 | |
---|
619 | SideEffects [list1 is modified] |
---|
620 | |
---|
621 | SeeAlso [Ord_ListMergeListUsingTable] |
---|
622 | |
---|
623 | ******************************************************************************/ |
---|
624 | void |
---|
625 | Ord_ListMergeList( |
---|
626 | lsList list1, |
---|
627 | lsList list2, |
---|
628 | Ord_ListMergeMethod method) |
---|
629 | { |
---|
630 | lsGen gen1; /* generator for list1 */ |
---|
631 | lsHandle handle; /* handle of an item in list1 */ |
---|
632 | lsGeneric data; |
---|
633 | st_table *dataToHandle1 = st_init_table(st_ptrcmp, st_ptrhash); |
---|
634 | |
---|
635 | /* |
---|
636 | * Load a hash table mapping each item in list1 to its handle in list1. |
---|
637 | */ |
---|
638 | gen1 = lsStart(list1); |
---|
639 | while (lsNext(gen1, &data, &handle) == LS_OK) { |
---|
640 | st_insert(dataToHandle1, (char *) data, (char *) handle); |
---|
641 | } |
---|
642 | (void) lsFinish(gen1); |
---|
643 | |
---|
644 | Ord_ListMergeListUsingTable(list1, list2, dataToHandle1, method); |
---|
645 | |
---|
646 | st_free_table(dataToHandle1); |
---|
647 | } |
---|
648 | |
---|
649 | |
---|
650 | /**Function******************************************************************** |
---|
651 | |
---|
652 | Synopsis [Appends list2 into list1.] |
---|
653 | |
---|
654 | Description [Appends list2 into list1. List1 is modified; list2 is not |
---|
655 | changed.] |
---|
656 | |
---|
657 | SideEffects [list1 is modified] |
---|
658 | |
---|
659 | ******************************************************************************/ |
---|
660 | void |
---|
661 | Ord_ListAppendList( |
---|
662 | lsList list1, |
---|
663 | lsList list2) |
---|
664 | { |
---|
665 | lsGen gen; |
---|
666 | lsHandle handle; /* unused */ |
---|
667 | lsGeneric data; |
---|
668 | |
---|
669 | /* |
---|
670 | * Walk through list2 forwards, inserting each element to the end of list1. |
---|
671 | */ |
---|
672 | gen = lsStart(list2); |
---|
673 | while (lsNext(gen, &data, LS_NH) == LS_OK) { |
---|
674 | (void) lsNewEnd(list1, data, &handle); |
---|
675 | } |
---|
676 | (void) lsFinish(gen); |
---|
677 | } |
---|
678 | |
---|
679 | |
---|
680 | /*---------------------------------------------------------------------------*/ |
---|
681 | /* Definition of internal functions */ |
---|
682 | /*---------------------------------------------------------------------------*/ |
---|
683 | |
---|
684 | /**Function******************************************************************** |
---|
685 | |
---|
686 | Synopsis [Compares the depth of two nodes in an lsList.] |
---|
687 | |
---|
688 | Description [Compares the depth of two nodes in an lsList. Greater depth |
---|
689 | node should appear before a lower depth node.] |
---|
690 | |
---|
691 | SideEffects [] |
---|
692 | |
---|
693 | ******************************************************************************/ |
---|
694 | int |
---|
695 | OrdNodesFromListCompareDepth( |
---|
696 | lsGeneric node1, |
---|
697 | lsGeneric node2) |
---|
698 | { |
---|
699 | return NodesCompareDepth((Ntk_Node_t *) node1, (Ntk_Node_t *) node2); |
---|
700 | } |
---|
701 | |
---|
702 | |
---|
703 | /**Function******************************************************************** |
---|
704 | |
---|
705 | Synopsis [Compares the depth of two nodes in an array_t.] |
---|
706 | |
---|
707 | Description [Compares the depth of two nodes in an array_t. Greater depth |
---|
708 | node should appear before a lower depth node.] |
---|
709 | |
---|
710 | SideEffects [] |
---|
711 | |
---|
712 | ******************************************************************************/ |
---|
713 | int |
---|
714 | OrdNodesFromArrayCompareDepth( |
---|
715 | const void * node1, |
---|
716 | const void * node2) |
---|
717 | { |
---|
718 | return NodesCompareDepth(*(Ntk_Node_t **) node1, *(Ntk_Node_t **) node2); |
---|
719 | } |
---|
720 | |
---|
721 | |
---|
722 | /**Function******************************************************************** |
---|
723 | |
---|
724 | Synopsis [Computes the depth of each node in the TFI of roots.] |
---|
725 | |
---|
726 | Description [Computes the depth of each node in the transitive fanin of the |
---|
727 | list of roots. The depth of a node is defined inductively: latches, and |
---|
728 | nodes with no inputs, have depth 0. Otherwise, the depth of a node is 1 more |
---|
729 | than the maximum depth over the node's fanins. Intuitively, the depth of a |
---|
730 | node is the length of the longest (backward) path from the node to a latch, |
---|
731 | primary input, pseudo input, or constant.] |
---|
732 | |
---|
733 | SideEffects [Uses undef field of Ntk_Node_t.] |
---|
734 | |
---|
735 | SeeAlso [Ord_NetworkOrderVariables] |
---|
736 | |
---|
737 | ******************************************************************************/ |
---|
738 | void |
---|
739 | OrdNetworkComputeNodeDepths( |
---|
740 | Ntk_Network_t * network, |
---|
741 | lsList roots /* list of Ntk_Node_t */) |
---|
742 | { |
---|
743 | lsGen gen; |
---|
744 | Ntk_Node_t *node; |
---|
745 | Ntk_Node_t *root; |
---|
746 | |
---|
747 | /* |
---|
748 | * Initialize the depth of each node to unassigned. |
---|
749 | */ |
---|
750 | Ntk_NetworkForEachNode(network, gen, node) { |
---|
751 | NodeSetDepth(node, ORDUNASSIGNED_DEPTH); |
---|
752 | } |
---|
753 | |
---|
754 | /* |
---|
755 | * Start the recursive computation from each root. |
---|
756 | */ |
---|
757 | lsForEachItem(roots, gen, root) { |
---|
758 | (void) NodeComputeDepth(root); |
---|
759 | } |
---|
760 | } |
---|
761 | |
---|
762 | |
---|
763 | /**Function******************************************************************** |
---|
764 | |
---|
765 | Synopsis [Prints the names of a list of nodes, one per line.] |
---|
766 | |
---|
767 | SideEffects [] |
---|
768 | |
---|
769 | ******************************************************************************/ |
---|
770 | void |
---|
771 | OrdNodeListWrite( |
---|
772 | FILE *fp, |
---|
773 | lsList nodeList) |
---|
774 | { |
---|
775 | lsGen gen; |
---|
776 | Ntk_Node_t *node; |
---|
777 | |
---|
778 | lsForEachItem(nodeList, gen, node) { |
---|
779 | (void) fprintf(fp, "%s\n", Ntk_NodeReadName(node)); |
---|
780 | } |
---|
781 | } |
---|
782 | |
---|
783 | |
---|
784 | /**Function******************************************************************** |
---|
785 | |
---|
786 | Synopsis [Reads the depth of a node.] |
---|
787 | |
---|
788 | SideEffects [] |
---|
789 | |
---|
790 | Comment [The depth is not stored in a hash table of orderingState, because, |
---|
791 | for OrdNodesFromArrayCompareDepth, we need to be able to access the depth of |
---|
792 | a node given *just* the node.] |
---|
793 | |
---|
794 | SeeAlso [NodeSetDepth OrdNodesFromArrayCompareDepth |
---|
795 | OrdNodesFromListCompareDepth] |
---|
796 | |
---|
797 | ******************************************************************************/ |
---|
798 | long |
---|
799 | OrdNodeReadDepth( |
---|
800 | Ntk_Node_t * node) |
---|
801 | { |
---|
802 | return ((long) Ntk_NodeReadUndef(node)); |
---|
803 | } |
---|
804 | |
---|
805 | |
---|
806 | /**Function******************************************************************** |
---|
807 | |
---|
808 | Synopsis [Assigns consecutive MDD ids to nodes in orderList.] |
---|
809 | |
---|
810 | Description [Assigns consecutive MDD ids to nodes in orderList. Ids are |
---|
811 | assigned starting from the number of variables in the MDD manager of |
---|
812 | network. (An MDD manager is created for the network if the network doesn't |
---|
813 | already have one.) OrderType can be Ord_All_c or Ord_InputAndLatch_c. If |
---|
814 | orderType is Ord_All_c, then all nodes in orderList are assigned an id. If |
---|
815 | orderType is Ord_InputAndLatch_c only primary inputs, pseudo input, latches, |
---|
816 | and latch NSs are assigned ids. Presently, nsAfterSupport is unused.<p>] |
---|
817 | |
---|
818 | SideEffects [] |
---|
819 | |
---|
820 | SeeAlso [OrdNetworkOrderTFIOfRoots Ntk_NetworkInitializeMddManager] |
---|
821 | |
---|
822 | ******************************************************************************/ |
---|
823 | void |
---|
824 | OrdNetworkAssignMddIds( |
---|
825 | Ntk_Network_t * network, |
---|
826 | Ord_OrderType orderType, |
---|
827 | lsList orderList, |
---|
828 | boolean nsAfterSupport) |
---|
829 | { |
---|
830 | lsGen gen; |
---|
831 | Ntk_Node_t *node; |
---|
832 | int mddId; |
---|
833 | mdd_manager *mddManager = Ntk_NetworkReadMddManager(network); |
---|
834 | array_t *mvarValues = array_alloc(int, lsLength(orderList)); |
---|
835 | array_t *mvarNames = array_alloc(char *, lsLength(orderList)); |
---|
836 | |
---|
837 | assert((orderType == Ord_All_c) || (orderType == Ord_InputAndLatch_c)); |
---|
838 | |
---|
839 | /* |
---|
840 | * If the network doesn't already have an MDD manager, then create one. In |
---|
841 | * any case, set mddId to be the number of variables currently existing in |
---|
842 | * the manager. |
---|
843 | */ |
---|
844 | if (mddManager == NIL(mdd_manager)) { |
---|
845 | mddManager = Ntk_NetworkInitializeMddManager(network); |
---|
846 | mddId = 0; |
---|
847 | } |
---|
848 | else { |
---|
849 | array_t *mvarArray = mdd_ret_mvar_list(mddManager); |
---|
850 | mddId = array_n(mvarArray); |
---|
851 | } |
---|
852 | |
---|
853 | lsForEachItem(orderList, gen, node) { |
---|
854 | /* |
---|
855 | * A node gets an MDD id if node is a combinational input, next state |
---|
856 | * node, or orderType is Ord_All_c. |
---|
857 | */ |
---|
858 | if (Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsNextStateNode(node) |
---|
859 | || (orderType == Ord_All_c) ) { |
---|
860 | |
---|
861 | Ntk_NodeSetMddId(node, mddId); |
---|
862 | mddId++; |
---|
863 | |
---|
864 | array_insert_last(int, mvarValues, |
---|
865 | Var_VariableReadNumValues(Ntk_NodeReadVariable(node))); |
---|
866 | array_insert_last(char *, mvarNames, Ntk_NodeReadName(node)); |
---|
867 | } |
---|
868 | } |
---|
869 | |
---|
870 | /* |
---|
871 | * Create the variables in the MDD manager. The last argument being NIL |
---|
872 | * means that the variables will not be interleaved. |
---|
873 | */ |
---|
874 | mdd_create_variables(mddManager, mvarValues, mvarNames, NIL(array_t)); |
---|
875 | |
---|
876 | array_free(mvarValues); |
---|
877 | array_free(mvarNames); |
---|
878 | } |
---|
879 | |
---|
880 | |
---|
881 | /*---------------------------------------------------------------------------*/ |
---|
882 | /* Definition of static functions */ |
---|
883 | /*---------------------------------------------------------------------------*/ |
---|
884 | |
---|
885 | /**Function******************************************************************** |
---|
886 | |
---|
887 | Synopsis [Compares depths of node1 and node2 for sorting; greater depth |
---|
888 | node should appear before a lower depth node. Ties are broken based on the |
---|
889 | node names; it's an error if the two nodes have the same name.] |
---|
890 | |
---|
891 | SideEffects [] |
---|
892 | |
---|
893 | ******************************************************************************/ |
---|
894 | static int |
---|
895 | NodesCompareDepth( |
---|
896 | Ntk_Node_t *node1, |
---|
897 | Ntk_Node_t *node2) |
---|
898 | { |
---|
899 | long depth1 = OrdNodeReadDepth(node1); |
---|
900 | long depth2 = OrdNodeReadDepth(node2); |
---|
901 | |
---|
902 | if (depth1 > depth2) { |
---|
903 | return -1; |
---|
904 | } |
---|
905 | else if (depth1 < depth2) { |
---|
906 | return 1; |
---|
907 | } |
---|
908 | else { |
---|
909 | char *name1 = Ntk_NodeReadName(node1); |
---|
910 | char *name2 = Ntk_NodeReadName(node2); |
---|
911 | |
---|
912 | /* |
---|
913 | * As a tiebreaker, sort based on name, so that the sorted result is not |
---|
914 | * sensitive to the order in which the nodes are passed to the compare |
---|
915 | * function. When sorting based on name, the order doesn't really matter, |
---|
916 | * but right now it's done so that "foo<i>" will come before "foo<j>" in |
---|
917 | * the ordering, where i < j. This is just a little heuristic to put lower |
---|
918 | * order bits first. */ |
---|
919 | if (strcmp(name1, name2) < 0) { |
---|
920 | return -1; |
---|
921 | } |
---|
922 | else if (strcmp(name1, name2) > 0) { |
---|
923 | return 1; |
---|
924 | } |
---|
925 | else { |
---|
926 | return 0; |
---|
927 | } |
---|
928 | } |
---|
929 | } |
---|
930 | |
---|
931 | |
---|
932 | /**Function******************************************************************** |
---|
933 | |
---|
934 | Synopsis [Computes the depth of a node.] |
---|
935 | |
---|
936 | SideEffects [] |
---|
937 | |
---|
938 | SeeAlso [OrdNetworkComputeNodeDepths] |
---|
939 | |
---|
940 | ******************************************************************************/ |
---|
941 | static long |
---|
942 | NodeComputeDepth( |
---|
943 | Ntk_Node_t * node) |
---|
944 | { |
---|
945 | long depth = OrdNodeReadDepth(node); |
---|
946 | |
---|
947 | /* |
---|
948 | * If the node's depth has already been computed (i.e. it's not unassigned), |
---|
949 | * then just return it below. If it's unassigned, then recursively compute |
---|
950 | * it. |
---|
951 | */ |
---|
952 | if (depth == ORDUNASSIGNED_DEPTH) { |
---|
953 | |
---|
954 | if (Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsConstant(node)) { |
---|
955 | /* |
---|
956 | * Latches, and nodes with no fanins, get depth 0. This is the terminal |
---|
957 | * case of recursion. |
---|
958 | */ |
---|
959 | depth = 0; |
---|
960 | } |
---|
961 | else { |
---|
962 | int i; |
---|
963 | Ntk_Node_t *fanin; |
---|
964 | /* |
---|
965 | * Compute the depth of each fanin node in the support of node, and |
---|
966 | * maintain the maximum. We start depth at 0 for max calculation. |
---|
967 | */ |
---|
968 | depth = 0; |
---|
969 | Ntk_NodeForEachFanin(node, i, fanin) { |
---|
970 | long faninDepth = NodeComputeDepth(fanin); |
---|
971 | |
---|
972 | depth = (depth > faninDepth) ? depth : faninDepth; |
---|
973 | } |
---|
974 | |
---|
975 | /* |
---|
976 | * The depth of node is one more than the max depths of its fanins. |
---|
977 | */ |
---|
978 | depth++; |
---|
979 | } |
---|
980 | |
---|
981 | /* |
---|
982 | * Store the depth. |
---|
983 | */ |
---|
984 | NodeSetDepth(node, depth); |
---|
985 | } |
---|
986 | |
---|
987 | return depth; |
---|
988 | } |
---|
989 | |
---|
990 | |
---|
991 | /**Function******************************************************************** |
---|
992 | |
---|
993 | Synopsis [Adds to nodeOrderList all network nodes not currently in the list.] |
---|
994 | |
---|
995 | Description [Adds to the end of nodeOrderList all network nodes that are not |
---|
996 | yet present in nodeOrderList. This is used to pick up those (dangling) |
---|
997 | nodes that weren't in the transitive fanins of the roots in the call to |
---|
998 | OrdNetworkOrderTFIOfRoots. nodeToHandle is a hash table mapping each node in |
---|
999 | nodeOrderList to its handle in the list; dangling nodes are inserted into |
---|
1000 | this table.] |
---|
1001 | |
---|
1002 | SideEffects [nodeOrderList and nodeToHandle will be modified if dangling |
---|
1003 | nodes exist.] |
---|
1004 | |
---|
1005 | SeeAlso [OrdNetworkOrderTFIOfRoots] |
---|
1006 | |
---|
1007 | ******************************************************************************/ |
---|
1008 | static void |
---|
1009 | NetworkAddDanglingNodesToOrderList( |
---|
1010 | Ntk_Network_t * network, |
---|
1011 | lsList nodeOrderList /* of Ntk_Node_t* */, |
---|
1012 | st_table *nodeToHandle /* Ntk_Node_t* to lsHandle */) |
---|
1013 | { |
---|
1014 | lsGen gen; |
---|
1015 | Ntk_Node_t *node; |
---|
1016 | |
---|
1017 | /* |
---|
1018 | * For each network node, if it's not in nodeOrderList, then add it to the |
---|
1019 | * end of the list. |
---|
1020 | * (NOTE: may be sensitive to ordering in memory.) |
---|
1021 | */ |
---|
1022 | Ntk_NetworkForEachNode(network, gen, node) { |
---|
1023 | if (!st_is_member(nodeToHandle, (char *) node)) { |
---|
1024 | lsHandle handle; |
---|
1025 | |
---|
1026 | (void) lsNewEnd(nodeOrderList, (lsGeneric) node, &handle); |
---|
1027 | st_insert(nodeToHandle, (char *) node, (char *) handle); |
---|
1028 | } |
---|
1029 | } |
---|
1030 | } |
---|
1031 | |
---|
1032 | |
---|
1033 | /**Function******************************************************************** |
---|
1034 | |
---|
1035 | Synopsis [Adds to nodeOrderList all next state variables.] |
---|
1036 | |
---|
1037 | Description [Adds to nodeOrderList all next state variables. If |
---|
1038 | nsAfterSupport is TRUE, then for a given latch, its NS variable is added in |
---|
1039 | nodeOrderList just after the latch's corresponding dataInput node. If |
---|
1040 | nsAfterSupport is FALSE, then for a given latch, its NS variable is added in |
---|
1041 | nodeOrderList just after the latch (i.e. its present state variable). (If the |
---|
1042 | latch itself is not present yet in the nodeOrderList, then first adds latch |
---|
1043 | to the end of the ordering.)<p> |
---|
1044 | |
---|
1045 | nodeToHandle is a hash table mapping each node in nodeOrderList to its |
---|
1046 | handle in the list; next state nodes are inserted into this table.] |
---|
1047 | |
---|
1048 | SideEffects [nodeOrderList and nodeToHandle will be modified if latches |
---|
1049 | exist.] |
---|
1050 | |
---|
1051 | SeeAlso [OrdNetworkOrderTFIOfRoots] |
---|
1052 | |
---|
1053 | ******************************************************************************/ |
---|
1054 | static void |
---|
1055 | NetworkAddNSVarsToOrderList( |
---|
1056 | Ntk_Network_t * network, |
---|
1057 | lsList nodeOrderList /* of Ntk_Node_t */, |
---|
1058 | st_table *nodeToHandle /* Ntk_Node_t* to lsHandle */, |
---|
1059 | boolean nsAfterSupport) |
---|
1060 | { |
---|
1061 | lsGen gen1; |
---|
1062 | Ntk_Node_t *latch; |
---|
1063 | |
---|
1064 | /* |
---|
1065 | * For each latch, add the latch's corresponding NS node to the ordering. |
---|
1066 | * (NOTE: may be sensitive to ordering in memory.) |
---|
1067 | */ |
---|
1068 | Ntk_NetworkForEachLatch(network, gen1, latch) { |
---|
1069 | lsHandle handle; |
---|
1070 | lsGen gen2; |
---|
1071 | lsGeneric dummyData; |
---|
1072 | Ntk_Node_t *latchNS = Ntk_NodeReadShadow(latch); |
---|
1073 | |
---|
1074 | if (nsAfterSupport) { |
---|
1075 | /* Add just after the latch's dataInput. */ |
---|
1076 | lsHandle dataInputHandle; |
---|
1077 | Ntk_Node_t *dataInput = Ntk_LatchReadDataInput(latch); |
---|
1078 | int status UNUSED = st_lookup(nodeToHandle, dataInput, |
---|
1079 | &dataInputHandle); |
---|
1080 | |
---|
1081 | assert(status); |
---|
1082 | gen2 = lsGenHandle(dataInputHandle, &dummyData, LS_AFTER); |
---|
1083 | } |
---|
1084 | else { |
---|
1085 | /* Add just after the latch. */ |
---|
1086 | lsHandle latchHandle; |
---|
1087 | int status = st_lookup(nodeToHandle, latch, &latchHandle); |
---|
1088 | |
---|
1089 | if (!status) { |
---|
1090 | /* |
---|
1091 | * Latch itself is not yet in the ordering. This can happen if the |
---|
1092 | * latch is not in the TFI of any other latch. So add the latch first |
---|
1093 | * (at the end of the ordering). |
---|
1094 | */ |
---|
1095 | (void) lsNewEnd(nodeOrderList, (lsGeneric) latch, &latchHandle); |
---|
1096 | st_insert(nodeToHandle, (char *) latch, (char *) latchHandle); |
---|
1097 | } |
---|
1098 | |
---|
1099 | gen2 = lsGenHandle(latchHandle, &dummyData, LS_AFTER); |
---|
1100 | } |
---|
1101 | |
---|
1102 | /* Actually add to list here. */ |
---|
1103 | (void) lsInAfter(gen2, (lsGeneric) latchNS, &handle); |
---|
1104 | st_insert(nodeToHandle, (char *) latchNS, (char *) handle); |
---|
1105 | (void) lsFinish(gen2); |
---|
1106 | |
---|
1107 | } |
---|
1108 | } |
---|
1109 | |
---|
1110 | |
---|
1111 | /**Function******************************************************************** |
---|
1112 | |
---|
1113 | Synopsis [Converts a list of latch next state nodes to the corresponding |
---|
1114 | list of latch data input nodes.] |
---|
1115 | |
---|
1116 | SideEffects [] |
---|
1117 | |
---|
1118 | ******************************************************************************/ |
---|
1119 | static lsList |
---|
1120 | LatchNSListConvertToLatchDataInputList( |
---|
1121 | lsList latchNSList) |
---|
1122 | { |
---|
1123 | lsGen gen; |
---|
1124 | Ntk_Node_t *node; |
---|
1125 | Ntk_Node_t *latch; |
---|
1126 | lsList latchDataInputList = lsCreate(); |
---|
1127 | |
---|
1128 | lsForEachItem(latchNSList, gen, node) { |
---|
1129 | assert(Ntk_NodeTestIsNextStateNode(node)); |
---|
1130 | latch = Ntk_ShadowReadOrigin(node); |
---|
1131 | (void) lsNewEnd(latchDataInputList, (lsGeneric) |
---|
1132 | Ntk_LatchReadDataInput(latch), LS_NH); |
---|
1133 | } |
---|
1134 | |
---|
1135 | return latchDataInputList; |
---|
1136 | } |
---|
1137 | |
---|
1138 | |
---|
1139 | /**Function******************************************************************** |
---|
1140 | |
---|
1141 | Synopsis [Sets the depth of a node.] |
---|
1142 | |
---|
1143 | SideEffects [] |
---|
1144 | |
---|
1145 | SeeAlso [OrdNodeReadDepth] |
---|
1146 | |
---|
1147 | ******************************************************************************/ |
---|
1148 | static void |
---|
1149 | NodeSetDepth( |
---|
1150 | Ntk_Node_t * node, |
---|
1151 | long depth) |
---|
1152 | { |
---|
1153 | Ntk_NodeSetUndef(node, (void *) depth); |
---|
1154 | } |
---|
1155 | |
---|
1156 | /**Function******************************************************************** |
---|
1157 | |
---|
1158 | Synopsis [Group all bdd vars corresponding to mdd vars initMddId to |
---|
1159 | initMddId + (blockSize-1) in a block which will not be split in reordering.] |
---|
1160 | |
---|
1161 | Description [Group all bdd vars corresponding to mdd vars initMddId to |
---|
1162 | initMddId + blockSize in a block which will not be reordered internally. |
---|
1163 | Ths bdd's corresponding to these mdd's should be contiguous; if not the |
---|
1164 | function will fail.] |
---|
1165 | |
---|
1166 | SideEffects [] |
---|
1167 | |
---|
1168 | ******************************************************************************/ |
---|
1169 | |
---|
1170 | static void |
---|
1171 | MddGroupVariables( |
---|
1172 | mdd_manager *mddMgr, |
---|
1173 | int initMddId, |
---|
1174 | int blockSize ) |
---|
1175 | { |
---|
1176 | int i, j; |
---|
1177 | int length; |
---|
1178 | int aIndex; |
---|
1179 | int startingBddIndex; |
---|
1180 | int sanityCheck; |
---|
1181 | mvar_type initMv, anMv; |
---|
1182 | bvar_type initBvar, aBvar; |
---|
1183 | array_t *mvar_list, *bvar_list; |
---|
1184 | bdd_t *bdd; |
---|
1185 | |
---|
1186 | mvar_list = mdd_ret_mvar_list(mddMgr); |
---|
1187 | bvar_list = mdd_ret_bvar_list(mddMgr); |
---|
1188 | |
---|
1189 | /* |
---|
1190 | * mvar for initMddId |
---|
1191 | */ |
---|
1192 | initMv = array_fetch(mvar_type, mvar_list, initMddId); |
---|
1193 | |
---|
1194 | /* |
---|
1195 | * bvar for first bdd for initMddId |
---|
1196 | */ |
---|
1197 | initBvar = mdd_ret_bvar(&initMv, 0, bvar_list); |
---|
1198 | |
---|
1199 | /* |
---|
1200 | * number of bdd variables to group |
---|
1201 | */ |
---|
1202 | length = 0; |
---|
1203 | |
---|
1204 | /* |
---|
1205 | * startingBddIndex is the level of the first bdd variable |
---|
1206 | */ |
---|
1207 | startingBddIndex = bdd_top_var_level( mddMgr, initBvar.node ); |
---|
1208 | sanityCheck = startingBddIndex; |
---|
1209 | |
---|
1210 | /* |
---|
1211 | * in this loop we are simply ensuring that the bdd variables |
---|
1212 | * corresponding to the mdd vars are infact contiguous. If this |
---|
1213 | * is not the case we fail. length is the total number of bdd variables |
---|
1214 | * to be grouped. |
---|
1215 | */ |
---|
1216 | for( i = 0; i < blockSize; i++) { |
---|
1217 | anMv = array_fetch(mvar_type, mvar_list, ( initMddId + i ) ); |
---|
1218 | for ( j = 0 ; j < anMv.encode_length; j++ ) { |
---|
1219 | |
---|
1220 | aBvar = mdd_ret_bvar( & anMv, j, bvar_list ); |
---|
1221 | aIndex = bdd_top_var_level( mddMgr, aBvar.node ); |
---|
1222 | |
---|
1223 | if ( sanityCheck != aIndex ) { |
---|
1224 | /* bdd vars are not contiguous!! */ |
---|
1225 | fprintf(vis_stderr, "Badly formed block - bdd vars for %s (mvar_id = %d) are not contiguous!!\n", |
---|
1226 | anMv.name, anMv.mvar_id ); |
---|
1227 | fail("Wont go on\n"); |
---|
1228 | } |
---|
1229 | else { |
---|
1230 | /* number of variables to group increased by one */ |
---|
1231 | sanityCheck++; |
---|
1232 | length++; |
---|
1233 | } |
---|
1234 | } |
---|
1235 | } |
---|
1236 | |
---|
1237 | bdd = bdd_var_with_index(mddMgr, startingBddIndex); |
---|
1238 | (void) bdd_new_var_block(bdd, length); |
---|
1239 | bdd_free(bdd); |
---|
1240 | } |
---|
1241 | |
---|
1242 | |
---|